XML.orgXML.org
FOCUS AREAS |XML-DEV |XML.org DAILY NEWSLINK |REGISTRY |RESOURCES |ABOUT
OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]
Do Not Emulate XML Namespaces in JSON

Hi Folks,

I've been digging into the issue of how to emulate XML namespaces – RDF, GML, XLINK, etc. – in JSON. Many people have proposed ways to do this. But they fail to take into account the impact their approach has on JSON Schema. Their approaches are incompatible with JSON Schema. Below I describe the various approaches and reveal their flaws. At the end I offer several conclusions.  /Roger

Transform this XML to JSON

Convert the following Book XML document to JSON. Incorporate its namespaces into the JSON version.

<book xmlns="http://www.book.org">
   
<title>The Unix Philosophy</title>
   
<author>Mike Gancarz</author>
   
<date xmlns="urn:rfc:3339">1994</date>
   
<publisher>Digital Press</publisher>
</book>

 

The XML document uses two namespaces: the book namespace (http://www.book.org) and the RFC namespace (urn:rfc:3339). The former is formatted as a URL, the latter as a URN. Default namespaces are used to avoid excessive clutter in the XML.

Approach #1 – Emulate Default Namespaces

In the JSON implementation of book, let's create an xmlns object property to denote a default namespace declaration:

{
   
"xmlns": "http://www.book.org",
   
"book": {
       
"title": "The Philosophy of Unix",
        
"author": "Mike Gancarz"
   
}
}

 

I omitted date and publisher. I'll come back to them in a moment.

For an XML-savvy person, the JSON looks quite reasonable. But it's important to note that xmlns has meaning only to XML applications, it means nothing to JSON applications. So we must specify the meaning of xmlns and then applications must be coded to understand those semantics.  For example, what is the scope of the default namespace declaration? Presumably, the namespace declaration applies to book, title, and author. Okay, the semantics is this: xmlns applies to the following sibling properties (in this case there is only one following sibling property, book) and to their values (title and author). Fine.

Now let's reintroduce date and publisher:

{
   
"xmlns": "http://www.book.org",
   
"book": {
       
"title": "The Philosophy of Unix",
       
"author": "Mike Gancarz",
       
"date": 1994,
       
"publisher": "Digital Press"
   
}
}

 

Clearly that JSON is not correct. According to the semantics we've established, date is in the book namespace, which it isn't. To remedy this, let's insert a second default namespace declaration, just prior to date:

{
   
"xmlns": "http://www.book.org",
   
"book": {
       
"title": "The Philosophy of Unix",
       
"author": "Mike Gancarz",
       
"xmlns": "urn:rfc:3339",
       
"date": 1994,
       
"publisher": "Digital Press"
   
}
}

 

That's not correct either because according to the semantics, both date and publisher are in the RFC namespace; date is, but publisher isn't.

Let's fix it by making the value of date an object and inserting the xmlns inside it:

{
   
"xmlns": "http://www.book.org",
   
"book": {
       
"title": "The Philosophy of Unix",
       
"author": "Mike Gancarz",
       
"date": {
           
"xmlns": "urn:rfc:3339",
           
"value": 1994
       
},
       
"publisher": "Digital Press"
   
}
}

Presumably the intent of the inner xmlns is that it applies to the parent date. But that's a different semantics than we defined earlier.

This approach is a failure. Let's try another approach.

Approach #2 – Emulate Namespace Prefixes

Recall that in XML we can namespace-qualify each element, like so:

<bk:book xmlns:bk="http://www.book.org">
   
<bk:title>The Unix Philosophy</bk:title>
   
<bk:author>Mike Gancarz</bk:author>
   
<rfc:date xmlns:rfc="urn:rfc:3339">1994</rfc:date>
   
<bk:publisher>Digital Press</bk:publisher>
</bk:book>

 

Let's emulate that in JSON:

{
   
"xmlns:bk": "http://www.book.org",
   
"xmlns:rfc": "urn:rfc:3339",
   
"bk:book": {
       
"bk:title": "The Philosophy of Unix",
       
"bk:author": "Mike Gancarz",
       
"rfc:date": 1994,
       
"bk:publisher": "Digital Press"
   
}
}

 

Notice the two namespace declarations with namespace prefixes:

    "xmlns:bk": "http://www.book.org",
   
"xmlns:rfc": "urn:rfc:3339",

 

Namespace declaration with a namespace prefix is something that XML applications understand but not JSON applications, so it must be carefully defined if we are to use it in JSON documents. In XML a namespace prefix is arbitrary. Is that to be carried over to JSON? Should JSON applications treat the following version as identical to the previous version?

{
   
"xmlns:foo": "http://www.book.org",
   
"xmlns:bar": "urn:rfc:3339",
   
"foo:book": {
       
"foo:title": "The Philosophy of Unix",
       
"foo:author": "Mike Gancarz",
       
"bar:date": 1994,
       
"foo:publisher": "Digital Press"
   
}
}

 

Presumably the "namespace declarations" at the top of the JSON object have a scope that covers the entire object. Suppose that somewhere deep inside the JSON is another namespace declaration with the  same prefix but a different value; does the inner namespace declaration override the outer namespace declaration?  

Argh! This is starting to introduce into JSON all the complexities of XML namespaces.

Even if we were willing to introduce all the complexities of XML namespaces into JSON, it still wouldn't work because it violates JSON Schema design rules. See the next section.

This approach is a failure. Let's try another approach.

Approach #3 – Emulate Expanded Names

The purpose of namespaces is to provide a way to uniquely identify things. Default namespaces and namespace prefixes are merely ways to avoid writing full, expanded names. We've seen that emulating default namespaces and namespace prefixes is an abysmal failure. So let's use expanded names, like so:

{
   
"{http://www.book.org}book": {
       
"{http://www.book.org}title": "The Philosophy of Unix",
       
"{http://www.book.org}author": "Mike Gancarz",
       
"{urn:rfc:3339}date": 1994,
       
"{http://www.book.org}publisher": "Digital Press"
   
}
}

 

The expanded names make JSON really verbose, which will really irritate JSON evangelists. But there is a deeper problem. It has to do with JSON Schema. (You will be validating your JSON documents against a JSON Schema, right?)

To facilitate reusability, JSON Schema provides something called a "definitions" section, which is simply a place to store your reusable sub-schemas. Below is a JSON Schema with a definition section, which contains a definition of title:

A sub-schema within the definitions section is referenced using $ref, which has a URL value (this is a key point!). The following JSON Schema shows a book object with a title property and the definition of title's value is pointed to using $ref:

The # symbol in #/definitions/title indicates that it is an internal reference.

From now on I will refer to the title within the definitions section as the "title handle".

Let's get back to the namespace issue. The title handle inside the definitions section needs a unique identifier to distinguish it from any other titles that people might create. Let's use a fully expanded name for the title handle:

"definitions": {
        
"{http://www.book.org}title": {"type": "string"}
}

 

$ref must reference that title handle using a matching expanded name: 

"$ref": "#/definitions/{http://www.book.org}title"

 

Recall that the value of $ref must be a valid URL. But #/definitions/{http://www.book.org}title is not a valid URL.

Using expanded names in JSON documents removes the possibility of using JSON Schema. Don't do it!

This approach is a failure. Let's try another approach.

Approach #4 – Use Path Names

Since #/definitions/{http://www.book.org}title is not a valid URI, let's use a name that makes it a valid URI. This appears to be a good name for the title handle:

"definitions": {
       
"book/title": {"type": "string"}
}

 

$ref would then be this:

"$ref": "#/definitions/book/title"

 

However, that's not valid. The only thing that can follow #/definitions/ is a name (no forward slashes allowed).

This approach is a failure. Let's try another approach.

Approach #5 – Use Unique, Non-URL Names

Here's a way to uniquely identify the title handle:

"definitions": {
       
"book-title": {"type": "string"}
}

 

That's a valid JSON Schema. It looks dorky. One may as well just use a UUID:

"definitions": {
       
"5e49136a-5977-4f35-83c9-e60dbc9b3f2a-title": {"type": "string"}
}

 

That is a really "ugly" JSON Schema.

Conclusions

Do not emulate XML namespaces in JSON.

Creating unique names in JSON documents is probably a worthy endeavor, particularly if you will be merging JSON objects.

We don't need the XML namespace mechanism to create unique names.

Creating unique names is simply a matter of creating long, verbose names. The longer it is, the more likely it is unique. The following JSON document contains unique names and is compatible with JSON Schema (which follows):

JSON Instance

{
   
"book": {
       
"book-title": "The Philosophy of Unix",
       
"book-author": "Mike Gancarz",
       
"rfc-date": "1994-01-01T00:00:00Z",
       
"book-publisher": "Digital Press"
   
}
}

 

JSON Schema

{
   
"$schema": "http://json-schema.org/draft-04/schema#",
   
"type": "object",
   
"properties": {
       
"book": {
           
"type": "object",
           
"properties": {
               
"book-title": {"$ref": "#/definitions/book-title"},
               
"book-author": {"$ref": "#/definitions/book-author"},
               
"rfc-date": {"$ref": "#/definitions/rfc-date"},
               
"book-publisher": {"$ref": "#/definitions/book-publisher"}
           
}
      
}
   
},
   
"additionalProperties": false,
   
"definitions": {
       
"book-title": {"type": "string"},
       
"book-author": {"type": "string"},
       
"rfc-date": {"type": "string", "format": "date-time"},
       
"book-publisher": {"type": "string"}
   
}
}

 

 



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]


News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 1993-2007 XML.org. This site is hosted by OASIS