====== Request for Comments: Jsonable interface ====== * Version: 1.0 * Date: 2010-03-14 * Author: Guilherme Blanco * Status: Inactive ===== Introduction ===== 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. ===== Motivation ===== 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. ===== The problem that arrises ===== 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. ===== Proposal ===== 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'); } } ===== Patch ===== Currently there's no patch related to this RFC. ===== Changelog ===== 2010-03-14 Guilherme Blanco: Initial creation.