Introducing JsonML

JsonML (JSON Markup Language) is an application of the JSON (JavaScript Object Notation) data-interchange format. The purpose of JsonML is to provide a compact format for transporting XML-based data via JSON.

Topics

A primary use case for this is to send XHTML across the wire to a JSON-aware client (e.g. web browser) and have it easily parse it into DOM elements. JsonML is an ideal format to transmit UI markup via JSON-RPC. It also provides an excellent mechanism for storing UI markup inside of JavaScript.

See how JsonML can help when building UI in Ajax applications. Also, the JsonML filter callback can easily be used to bind behaviors to DOM elements for implementing techniques such as "Progressive Enhancement".

Learn how any arbitrary XML is transformed into JsonML via a simple XSLT.

For an interesting exercise, see how to convert DOM elements to JsonML and back.

News

JsonML + Browser-Side Templating

A BST system utilizing JsonML has been released which demonstrates the strengths of templating on the client: JsonML+BST.

JsonML2 - no object modifications

Following Douglas Crockford's move to make JSON a global object rather than extensions to the JavaScript objects, a compatible JsonML2.js has been produced.

JsonML MIME type

Very little precedent has been set (SPARQL, ATOM) on how to assign the MIME media type of JSON-based formats. Following the the "+xml" suffix convention [RFC3023], the unofficial MIME type for JsonML is: application/jsonml+json

"Get to know JsonML"

A good JsonML article was recently published on IBM developerWorks. The author walks the reader through some good background on Ajax & JSON before delving into a tutorial of JsonML usage.

Examples

To see JsonML+BST in action, play with the live JsonML+BST Example.

Other demonstrations give an idea of the expressive power of JsonML. They also demonstrate the power of the JsonML filter callback for binding behaviors to DOM elements.

Downloads

An open source JsonML builder. It is built in the spirit of Douglas Crockford's JavaScript JSON implementation, and requires json.js:
JsonML UI Builder: JsonML.js (4.40K)
JSMin'd UI Builder: JsonML.js (1.44K)
An alternate builder which doesn't modify the native String/Array objects. Requires json2.js:
JsonML2 UI Builder: JsonML2.js (5.62K)
JSMin'd UI Builder: JsonML.js (2.08K)
An open source JsonML+BST template data-binding script:
Template Data Binder: JsonML_BST.js (2.13K)
JSMin'd version: JsonML_BST.js (679 bytes)
An open source JsonML+BST Template Compiler:
Compiled Binary for .NET Framework 2.0 (40.4K)
C# Source for .NET Framework 2.0 (80.9K)
An open source transformation which converts any XML-based document into JsonML:
XML-to-JsonML XSLT: JsonML.xsl (6.49K)
An open source script which converts DOM elements back into JsonML:
DOM-to-JsonML Script: Dom2JsonML.js (1.12K)
Open source license

Feedback

Feedback is welcome. If this sounds useful to you, send an email. If you have suggestions which are consistent with the intent here, please feel free to share them.

- Stephen M. McKamey

jsonml@jsonml.org

Grammar (BNF)

The following grammar represents how XML-based markup (e.g. XHTML) is encoded into JsonML. As per JSON, whitespace is permitted between tokens.

element
= '[' tag-name ',' attributes ',' element-list ']'
| '[' tag-name ',' attributes ']'
| '[' tag-name ',' element-list ']'
| '[' tag-name ']'
| json-string
;
tag-name
= json-string
;
attributes
= '{' attribute-list '}'
| '{' '}'
;
attribute-list
= attribute ',' attribute-list
| attribute
;
attribute
= attribute-name ':' attribute-value
;
attribute-name
= json-string
;
attribute-value
= json-string
;
element-list
= element ',' element-list
| element
;

Usage Recommendations

Order of elements: tag-name, attribute, element-list.

Implementors MUST serialize the tag-name of the element before attributes or before any element-list. This is because any child text nodes will be siblings to the tag-name of the element. Implementors MUST serialize attributes before any child element as it is more natural to finish populating element attributes before moving onto other elements.

XHTML DOM Quirks.

While the process is fairly straight forward to recursively hydrate the element tree from JsonML, there are a number of inconsistencies and quirks to be aware of.

Colorful Table Example

Rendered in DOM:

#5D28D1 Example text here
#AF44EF 127310656
#AAD034  © 

XHTML Markup (516 bytes):

<table class="MyTable" style="background-color:yellow">
<tr>
<td class="MyTD" style="border:1px solid black">
#5D28D1</td>
<td class="MyTD" style="background-color:red">
Example text here</td>
</tr>
<tr>
<td class="MyTD" style="border:1px solid black">
#AF44EF</td>
<td class="MyTD" style="background-color:green">
127310656</td>
</tr>
<tr>
<td class="MyTD" style="border:1px solid black">
#AAD034</td>
<td class="MyTD" style="background-color:blue">
&nbsp;
<span style="background-color:maroon">&copy;</span>
&nbsp;
</td>
</tr>
</table>

JsonML Markup (558 bytes):

["table",
{
"class" : "MyTable",
"style" : "background-color:yellow"
},
["tr",
["td",
{
"class" : "MyTD",
"style" : "border:1px solid black"
},
"#550758"
],
["td",
{
"class" : "MyTD",
"style" : "background-color:red"
},
"Example text here"
]
],
["tr",
["td",
{
"class" : "MyTD",
"style" : "border:1px solid black"
},
"#993101"
],
["td",
{
"class" : "MyTD",
"style" : "background-color:green"
},
"127624015"
]
],
["tr",
["td",
{
"class" : "MyTD",
"style" : "border:1px solid black"
},
"#E33D87"
],
["td",
{
"class" : "MyTD",
"style" : "background-color:blue"
},
"\u00A0",
["span",
{ "style" : "background-color:maroon" },
"\u00A9"
],
"\u00A0"
]
]
]

Bulleted List Example

Rendered in DOM:

XHTML Markup (173 bytes):

<ul>
<li style="color:red">First Item</li>
<li title="Some hover text." style="color:green">
Second Item
</li>
<li><span class="code-example-third">Third</span>
Item</li>
</ul>

JsonML Markup (184 bytes):

["ul",
["li",
{ "style" : "color:red" },
"First Item"
],
["li",
{
"title" : "Some hover text.",
"style" : "color:green"
},
"Second Item"
],
["li",
["span",
{ "class" : "code-example-third" },
"Third"
],
" Item"
]
]