Note that there are some explanatory texts on larger screens.

plurals
  1. POSerializing PHP object to JSON
    primarykey
    data
    text
    <p>So I was wandering around <a href="http://php.net">php.net</a> for information about serializing PHP objects to JSON, when I stumbled across the new <a href="http://www.php.net/manual/en/class.jsonserializable.php">JsonSerializable Interface</a>. It's only <strong>PHP >= 5.4</strong> though, and I'm running in a 5.3.x environment.</p> <p>How is this sort of functionality achieved <strong>PHP &lt; 5.4</strong>?</p> <p>I've not worked much with JSON yet, but I'm trying to support an API layer in an application, and dumping the data object (<em>that would otherwise be sent to the view</em>) into JSON would be perfect.</p> <p>If I attempt to serialize the object directly, it returns an empty JSON string; which is because I assume <code>json_encode()</code> doesn't know what the heck to do with the object. Should I recursively reduce the object into an array, and then encode <em>that</em>?</p> <hr> <h1>Example</h1> <pre><code>$data = new Mf_Data(); $data-&gt;foo-&gt;bar['hello'] = 'world'; </code></pre> <p><strong><code>echo json_encode($data)</code></strong> produces an empty object:</p> <pre><code>{} </code></pre> <p><strong><code>var_dump($data)</code></strong> however, works as expected:</p> <pre><code>object(Mf_Data)#1 (5) { ["_values":"Mf_Data":private]=&gt; array(0) { } ["_children":"Mf_Data":private]=&gt; array(1) { [0]=&gt; array(1) { ["foo"]=&gt; object(Mf_Data)#2 (5) { ["_values":"Mf_Data":private]=&gt; array(0) { } ["_children":"Mf_Data":private]=&gt; array(1) { [0]=&gt; array(1) { ["bar"]=&gt; object(Mf_Data)#3 (5) { ["_values":"Mf_Data":private]=&gt; array(1) { [0]=&gt; array(1) { ["hello"]=&gt; string(5) "world" } } ["_children":"Mf_Data":private]=&gt; array(0) { } ["_parent":"Mf_Data":private]=&gt; *RECURSION* ["_key":"Mf_Data":private]=&gt; string(3) "bar" ["_index":"Mf_Data":private]=&gt; int(0) } } } ["_parent":"Mf_Data":private]=&gt; *RECURSION* ["_key":"Mf_Data":private]=&gt; string(3) "foo" ["_index":"Mf_Data":private]=&gt; int(0) } } } ["_parent":"Mf_Data":private]=&gt; NULL ["_key":"Mf_Data":private]=&gt; NULL ["_index":"Mf_Data":private]=&gt; int(0) } </code></pre> <hr> <h1>Addendum</h1> <h2>1)</h2> <p>So this is the <code>toArray()</code> function I've devised for the <code>Mf_Data</code> class:</p> <pre><code>public function toArray() { $array = (array) $this; array_walk_recursive($array, function (&amp;$property) { if ($property instanceof Mf_Data) { $property = $property-&gt;toArray(); } }); return $array; } </code></pre> <p>However since the <code>Mf_Data</code> objects also have a reference to their parent (<em>containing</em>) object, this fails with recursion. Works like a charm though when I remove the <code>_parent</code> reference.</p> <h2>2)</h2> <p>Just to follow up, the final function to transform a complex tree-node object I went with was:</p> <pre><code>// class name - Mf_Data // exlcuded properties - $_parent, $_index public function toArray() { $array = get_object_vars($this); unset($array['_parent'], $array['_index']); array_walk_recursive($array, function (&amp;$property) { if (is_object($property) &amp;&amp; method_exists($property, 'toArray')) { $property = $property-&gt;toArray(); } }); return $array; } </code></pre> <h2>3)</h2> <p>I'm following up again, with a bit cleaner of an implementation. Using interfaces for an <code>instanceof</code> check seems much cleaner than <code>method_exists()</code> (<em>however <code>method_exists()</code> does cross-cut inheritance/implementation</em>).</p> <p>Using <code>unset()</code> seemed a bit messy too, and it seems that logic should be refactored into another method. However, this implementation <em>does</em> copy the property array (<em>due to <code>array_diff_key</code></em>), so something to consider.</p> <pre><code>interface ToMapInterface { function toMap(); function getToMapProperties(); } class Node implements ToMapInterface { private $index; private $parent; private $values = array(); public function toMap() { $array = $this-&gt;getToMapProperties(); array_walk_recursive($array, function (&amp;$value) { if ($value instanceof ToMapInterface) { $value = $value-&gt;toMap(); } }); return $array; } public function getToMapProperties() { return array_diff_key(get_object_vars($this), array_flip(array( 'index', 'parent' ))); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload