Martin Atkins (mart) wrote in apparentlymart,
Martin Atkins

A Round-trippable Mapping Between JSON and XML

One thing I like about JSON is that it has types that map nicely on to types found in most everyday programming languages: strings, numbers, booleans, arrays, maps and null. XML, on the other hand, has basically two types: "element" and string. Element doesn't map particularly well onto any everyday programming language. Apparently, though, some frameworks make it easier to parse XML than JSON. (Go figure!) Certain protocols are requiring XML to be supported as a lossy transformation of JSON. I got to thinking that it would be useful to have an XML-based data format that can map to and from JSON without losing information.

Here's a stab at it. The main goal here is to structure it so that if you don't care about JSON's types you can just ignore the annotations and do things "the XML way", with XPath or XQuery or whatever's your poison. If you want to map it to a native data structure in your programming language, all of the type information provided by JSON is available, albeit in a much more verbose way. Let me demonstrate with an example. Here's some JSON-encoded data:

	"displayName": "Martin Atkins",
	"urls": [
	"accounts": [
			"domain": "",
			"username": "apparentlymart",
			"domain": "",
			"username": "Mart",
	"human": true,
	"favoriteNumber": 5,
	"names": {
		"familyName": "Atkins",
		"givenName": "Martin"
	somethingElse: null

Now here's the equivalent XML-encoded-JSON:

<json:root xmlns="">
	<displayName>Martin Atkins</displayName>
	<human json:type="boolean">true</human>
	<favoriteNumber json:type="number">5</favoriteNumber>
	<somethingElse json:type="null" />

I'm sure you can guess the mapping from the above, but I'll spell it out a bit anyway:

  • The root element is always root in a special namespace.
  • Every JSON value maps onto an XML element where the name is not significant.
  • An object maps to an element with non-namespaced child elements representing the values with the element name set to the key name.
  • An array maps to an element with only namespaced li child elements, each of which represents a value from the array in order.
  • A scalar value maps to an element containing only a text node. If there's no type attribute it's considered to be a string. Otherwise, the type attribute can be boolean, number or null.
  • For scalar values of type boolean, the text content is either true or false.
  • For scalar values of type number the text content is the number written out in base ten with optional decimal digits separated by an ASCII period.
  • For scalar values of type null the text content is the empty string, or the element uses empty element syntax.

If all formats that are requiring both JSON and XML use something like the above for their XML, then the XML output becomes a more verbose serialization of the JSON data model, and the data model doesn't need to be dumbed down to fit inside XML. A single, generic library can be written that can do the mapping in both directions. The only constraint this places on the input JSON is that the key names must only contain characters valid in XML element names. Obviously the namespace doesn't necessarily need to have "json" in its name; it's just an example. I'm sure there must already be something like this out there, but all I can find is things for encoding XML as JSON -- usually lossily -- which seems like the wrong way around to me.


  • Moved to TypePad is now hosted on TypePad rather than LiveJournal. All of the old content remains over here in LiveJournal land, but those who are…

  • Moving the Goalposts

    In the few weeks since I published the first drafts of AtomActivity, ActivitySchema and friends several things have come about: FriendFeed is…

  • Activity Streams and Comment Aggregation

    One pain point that exists for activity streams right now is the dispersal of responses over various networks. When I post a blog entry like this…

  • Post a new comment


    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.