JsonSerializableインターフェース
jsViewsについて書こうと思ったんですが、ちょっと寄り道。。。
むー、つい最近まで知らなかった。。。PHP5.4.0から追加されたようですね。JsonSerializableインターフェースのドキュメントは以下のURLです。
オブジェクトをそのままjson_encodeしてJSONデータにしたい場合、publicなメンバー変数のみJSONデータに現れます。たとえば、以下のようなコードの場合、
<?php namespace JsonSerializableTest; class Customer { public $id; protected $name; private $birthday; public function __construct($id, $name, \DateTime $birthday) { $this->id = $id; $this->name = $name; $this->birthday = $birthday; } public function getName() { return $this->name; } public function getBirthday() { return $this->birthday; } } $obj = new Customer('1', 'foo', new \DateTime('1970-01-01')); echo json_encode($obj, JSON_PRETTY_PRINT);
これを実行すると、メンバー変数"name"と"birthday"は出力されません。
{ "id": "1" }
ここで、PHP5.4.0から導入されたJsonSerializableインターフェースをimplementsし、定義されているjsonSerializeメソッドを実装することで、json_encodeする際に任意のデータを出力できるようになります。
たとえば、上記の非publicメンバーも出力する場合は以下のようなコードになります。
<?php namespace JsonSerializableTest; class Customer implements \JsonSerializable { public $id; protected $name; private $birthday; public function __construct($id, $name, \DateTime $birthday) { $this->id = $id; $this->name = $name; $this->birthday = $birthday; } public function getBirthday() { return $this->birthday; } public function jsonSerialize() { $object = new \stdClass(); $object->id = $this->id; $object->name = $this->name; $object->birthday = $this->birthday->format('Y/m/d'); return $object; } } $obj = new Customer('1', 'foo', new \DateTime('1970-01-01')); echo json_encode($obj, JSON_PRETTY_PRINT);
この実行は次のようになります。
{ "id": "1", "name": "foo", "birthday": "1970\/01\/01" }
いちいちメンバー変数を書くのが面倒な場合は、こんな感じでもOKです。
<?php namespace JsonSerializableTest; class Customer implements \JsonSerializable { : public function jsonSerialize() { $object = new \stdClass(); $class = new \ReflectionClass($this); foreach ($class->getProperties() as $property) { $property->setAccessible(true); $property_name = $property->getName(); $object->$property_name = $property->getValue($this); } return $object; } }
この場合は次のような感じになります。
{ "id": "1", "name": "foo", "birthday": { "date": "1970-01-01 00:00:00", "timezone_type": 3, "timezone": "Asia\/Tokyo" } }
追記(2012/10/25 18:50)
Reflectionが面倒な場合は、これでもOKです。
<?php namespace JsonSerializableTest; class Customer implements \JsonSerializable { : public function jsonSerialize() { return (object)get_object_vars($this); } }