title: Serialize/unserialize PHP object-graph to JSON
body: <p>I wanted to serialize a complete PHP object-graph to a JSON string representation, and unserialize it back to an identical PHP object-graph.</p>
  
  <p>Here is a summary of options I considered, and reasons why they don't work for me:</p>
  
  <ul>
  <li><p><code>serialize()</code> doesn't do what I want, because it uses a format specific to PHP. I want a format that is widely supported by most languages, and human-readable/editable.</p></li>
  <li><p><code>json_encode()</code> doesn't do what I want, because it only does simple values and arrays, not objects. (I'm actually using this in my implementation, see below.)</p></li>
  <li><p><code>var_export()</code> doesn't handle circular references, and doesn't do what I want (see above.) <em>(note that my current implementation does not handle circular references either - see comments and reply below for clarification of this issue.)</em></p></li>
  <li><p>Sebastian Bergmann's <a href="https://github.com/sebastianbergmann/php-object-freezer" rel="nofollow">Object Freezer</a> is a nice implementation, but it doesn't do what I want either - it uses a very long form, and relies on stuffing serialized objects with GUIDs.</p></li>
  <li><p><a href="https://github.com/ktomk/Serialized" rel="nofollow">Serialized</a> doesn't do what I want - it does not actually perform serialization, it parses the output of <code>serialize()</code> and produces a different representation, e.g. XML, but is unable to parse that representation. (it also does not support JSON - XML is very long form, and is not what I want.)</p></li>
  </ul>
  
  <p>I now have a working implementation to share:</p>
  
  <p><a href="https://github.com/mindplay-dk/jsonfreeze" rel="nofollow">https://github.com/mindplay-dk/jsonfreeze</a></p>
  
  <p>The JSON-representation of the object-graph looks like this:</p>
  
  <pre><code>{
      "#type": "Order",
      "orderNo": 123,
      "lines": [{
          "#type": "OrderLine",
          "item": "milk \"fuzz\"",
          "amount": 3,
          "options": null
      }, {
          "#type": "OrderLine",
          "item": "cookies",
          "amount": 7,
          "options": {
              "#type": "#hash",
              "flavor": "chocolate",
              "weight": "1\/2 lb"
          }
      }],
      "paid": true
  }
  </code></pre>
  
  <p>This approach is designed to work for a pure tree-structure aggregate - circular references are not allowed, nor multiple references to the same objects. In other words, this is not general-purpose like e.g. <code>serialize()</code> and <code>unserialize()</code> which function for any PHP object-graph.</p>
  
  <p>In my <a href="https://gist.github.com/2630741/17041e14f58c8c2ecc30b1dabdfe5e8f87460412" rel="nofollow">initial approach</a> I used a serialized form that was essentially a base-0 list of objects. The first object in the list (number 0) is the root of the serialized object-graph, any other objects are stored in the order they're found.</p>
  
  <p>In the current implementation, the JSON representation resembles the original tree-structure to the extend that this is possible, making it possible to actually work with the JSON representation of an object-graph in JavaScript. The only deviation is the magic <code>#type</code> property (prefixed with # to prevent collision with property-names) and the <code>#hash</code> "type", used to distinguish <code>array</code>-type hashes (stored as JSON objects) from regular <code>array</code>-type arrays (stored as JSON arrays).</p>
  
  <hr>
  
  <p><em>I'm leaving these notes about the previous version here for historical purposes.</em></p>
  
  <p>Circular references are handled simply by never storing nested objects inside the serialized representation of each object - instead, any object-reference is stored as a JSON-object with the object-index - e.g. <code>{"__oref":2}</code> is a reference to the object with index <code>2</code> in the object-list.</p>
  
  <p>I'm having a problem with array-references in my implementation - when I var_dump() inside the code that restores references to objects to the array, they are being populated, but at some point the array gets copied, and you end up with the empty copy. I've tried placing <code>&amp;</code> characters everywhere in the code, but regardless of where I pass by reference, the end-result is an empty array.</p>