The current state of JSON support in PHP deals with all scalar types smoothly. However, complex data structures cannot be handled by PHP API. This proposal wants to describe a clean way to include this support via implementation of an interface.
Consider this piece of code:
class Person { public $name; protected $age; private $salary; public function __construct($name, $age, $salary) { $this->name = $name; $this->age = $age; $this->salary = $salary; } // ... } $person = new \Person('Jesus Christ', 32, 10000); echo json_encode($person);
PHP is able to convert public variables, so the return of this script will be:
{"name": "Jesus Christ"}
However, we may want json_(encode|decode) to also export/import protected and private information.
PHP json_decode is unable to recognize which class it is meant to be. Two solutions come to our hands:
* Drop json_decode reversal functionality. This is not an optimal solution, since we want to keep both json_encode and json_decode compatibility * Append some reverse engineer information allowing PHP to recognize what class it is.
The second solution can be fixed by attaching a CLASS information to JSON data. Taking our previous example (aswell as the expected behavior), it would generate:
{"__CLASS__": "Person", "name": "Jesus Christ", "age": 32, "salary": 10000}
Including export information is not ideal since it would actually be equal to the Serializable support.
A non-intrusive solution should be smooth just like SPL Serializable interface.
interface Jsonable { public function __toJson(); }
It is well known that at this stage, any developer is able to write a piece of code (a method) like the following one to include a similar support:
class Person implements Jsonable { public function __toJson() { $str = '{"__CLASS__": "' . get_class($this) . '"'; $reflClass = new \ReflectionClass($this); foreach ($reflClass->getProperties() as $reflProperty) { $reflProperty->setAccessible(true); $value = $reflProperty->getValue($this); $str .= ', ' . json_encode($reflProperty->getName()) . ': '; if (is_object($value) && $value instanceof Jsonable) { $str .= $value->__toJson(); } else if ( ! is_resource($value)) { $str .= json_encode($value); } } $str .= '}'; return $str; } }
By implementing natively Jsonable, it would be simply necessary to:
class Person { // ... public function __toJson() { return array('name', 'age', 'salary'); } }
It would be even possible to add custom export support, example:
class Person { // ... public function __toJson() { return array('salary'); } }
Currently there's no patch related to this RFC.
2010-03-14 Guilherme Blanco: Initial creation.