X

Sundararajan's Weblog

  • Java
    October 16, 2006

A convention for circular reference handling with JSON

Guest Author

Update: I was not aware of JSPON - JavaScript Persistent Object Notation (JSPON) - which addresses the problem below (I wrote the text below before my knowledge of JSPON!). Thanks to Andres Almiray for pointing me about that.

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. JSON can be used as replacement for XML (AJAX without the "X" for XML).

But, JSON does not have syntax for circular references - most JSON libraries expect the data structure to-be-serialized to have no cycles. In XML, typically special attributes such as ID and IDREF (or HREF in HTML) are used to create links between elements. (see also XML:id).

Here is a proposal for simple conventions to handle circular references. We can use few special properties with name starting with a "$". "$id" property uniquely identifies a JSON object within a JSON document. Such objects can be referred elsewhere by "$idref". In addition, we may "reserve" all properties starting with a letter "$".

Few examples:

  • $id

    String valued property that identifies an object uniquely within a JSON
    document/file.

  • $idref

    String valued property that refers to another object within the same JSON
    document/file.


    Example:

    {
    "$id" : "thisobj",
    "name": "Simple object",
    "date": { "day" : 16, "month": 10, "year": 2006},
    "mycontainer" : { "$idref": "thisobj" }
    }

    In the above example, "mycontainer" property refers back to the JSON object
    that contains "name", "date" and "mycontainer" properties.

  • $id for arrays

    Since, we cannot add "$xxx" properties to JSON arrays, we need a slighly different mechanism for hanlding array references. We can serialize an array that will be
    referred elsewhere as follows:

    • wrap it with an object. Add "$id" to the object.
    • add a property with a name "$" to the object - the value of this property
      is the array (that will be referred).

    Example:

    {
    "x": { "$id" : "myarray" , "$": [2, 3, 54654] },
    "y": { "$idref": "myarray" }
    }
  • $class

    "$class" property helps while mapping JSON objects back to language specific
    objects - for example, objects of specific Java bean classes. "$class"
    property may be used differently with other language bindings. For example,
    with JavaScript, the value of this property may be treated as a code string
    that will be evaluated to get "prototype" of the object being parsed. This way


    {
    "$class" : "java.util.Date",
    "day" : 16,
    "month" : 9,
    "year": 106,
    }

    After deserialization, the object will have two array valued properties
    "x" and "y" both would point to the same array.

  • $href

    String valued property that refers to another JSON document/file - like
    HTML Anchor tag. Also, "fragment" identifiers can be mapped to "$id" within the referred JSON URI. This way we can have "network" of JSON documents. Such "href"-ed fragments may be loaded using XMLHttpRequest or some such mechanism [may be lazily when that property is referred for the first time].

I've checked-in Java classes to serialize/de-serialize JSON with the above "extensions" at http://scripting.dev.java.net - the code is here

There is one issue with this scheme - with JavaScript we can deserialize JSON with "$id" and "$idref" etc. and resolve references, it is difficult to serialize. There is IdentityHashMap or equivalent in (pure) JavaScript [did I miss any such cool-trick?]. To detect whether we have serialized an object already or not [so that we can generate $idref instead of serializing it again], we may have to keep a list of visited objects (i.e, JS array) and walk through that list everytime and so the implementation would be slow for bigger object graphs. Note that this issue does not arise with Rhino implementation - because we can use IdentityHashMap API with Rhino.

Join the discussion

Comments ( 1 )
  • Andres Almiray Monday, October 16, 2006
    Sundar, there is already a proposal for special attributes in JSON related to persistence similar to what you describe here, might help. http://www.jspon.org/
    Regarding the serialize/de-serialize (JSON-Java), Json-lib (http://json-lib.sourceforge.net) will help you achieve that goal with ease, thanks to its JSONSerializer. The produced JSON strings do not carry information about the original or target class, in the time being you have to tell the serializer the target class or classes you want to convert to.
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.