- does not entirely make it clear what should go into a tag attribute versus a nested tag
- conversion of those two features into a unified internal datatype can be tricky (for example, this property led to choices that for erlang's xmerl causes a security regression if you are handling user-submitted xml).
- first class support for text inside of a tag is not what you want in 90% of data interchange events, and support for it creates a burden when deserializing.
- it's confusing what should be a text inside a tag versus a tag attribute. Or should that text be parsed into a number? At least JSON is strongly typed, you know what datatype is what just by looking at it.
- because there aren't good "best practices" around it, everyone rolls their XML schemas with their own ideas about what sort of thing should go where.
The major benefit of XML is its obession with schematization means that at least in many case you can grab a schema and figure out an appropriate declarative command to obtain what you want (if you have the right library), but this has basically been conquered in JSONland using JsonSchema/OpenAPI, and stuff like JsonLogic.
JSON's types are pretty anemic compared to the XMLSchema's datatypes[0]. Even it you don't use all of XSD's complex type system, having these basic datatypes is extremely useful and I wish JSON had similar.
The same thing is true if you replace “JSON” and “XMLSchema” with “XML” and “JSON Schema”, respectively.
And also, though less so, if you do the same but replace “XML Schema” with “JSON” instead of “JSON Schema”.
- JSON has just one escape format and all unicode codepoints can be used. XML generally allows only certain unicode codepoints, at some places like element names its further restricted (Quick: Which characters are not allowed? What's the difference between XML 1.0 and 1.1 here?). XML escapes at every place differently. In comments you need to escape less than elsewhere. In attributes you can use newlines but they will get normalized to spaces, you have to hex-encode newlines. There's Cdata.
- JSON doesn't have the entity madness with potential security issues.
- JSON doesn't have namespaces that add a lot of complexity with little benefit
Consider how you'd write these 2 bits of XML in JSON:
<A><B>foo</B><C>bar</C></A>
vs.
<A><B>too</B><C>bar</C><B>uh oh</B></A>
Without a schema, in the first case, how do you determine whether B should be "foo" or ["foo"]? In the second how do you preserve the relative ordering of B #1, C and B #2?
I worked on a project where we had a parse tree that we wanted to serialize out, and for this reason XML was the natural choice.
vs.
{ "a": [ { "b": "too" }, { "c": "bar" }, { "b": "uh oh" } ] }
- Only ever have a single key in each JSON object (treating them as tuples)
- Make all object values arrays.
It makes for some very unnatural looking JSON.
Otherwise it's very clear about the data's format and when there's ordering required
Not to me; its a fairly standard and natural JSON pattern. It’s tue that it use is usually quite limited in any given representation, but usually the thing you are modelling in JSON isn’t general XML with no further knowledge of application domain or logical schema.
This looks like line noise to me. All that punctuation and quoting looks ridiculous. What is the problem with straightforward and trivial to parse things like
[a]
b = foo
c = bar
or even a.b = foo
a.c = bar {a_list:[{text: too, type: b}, {text: bar, type: c}, {text: uh_oh, type: b}]}}
But generally you shouldn't have a mixed type list in json unless it's a deliberate choice, the "limitations" of json are exactly what devs want because it corresponds to a clarity of thought and purpose that simply isn't there in XML.We wanted a parse tree that could be serialized out to produce the original document byte for byte, but still reflected the grammar.
Things get uglier for JSON in the real world case:
"5+7 #comment"
becomes: <sum><integer>5</integer><operation>+</operation><integer>7</integer> #comment</sum>
The XML output is essentially the original input + grammar markup. Your solution also works but is a data structure representation with a lot more line noise for humans to read.This was primarily a mechanism to load parsed documents in to code that didn't have access to the recursive descent parser that parsed the document, for either security or performance reasons.
Loading the XML with the appropriate parse flags, doing a pre-order traversal on all the leaf PCDATA, and then printing it out, would regenerate the original document byte for byte.
Perhaps I should go back and implement JSON output and see how I feel about it... thought I'm pretty sure once you introduce a bunch of "text" and "type" fields to the JSON tree it's going to look a lot less readable than XML markup.
There are other fields as well like line and column numbers (output as XML attributes)
I've had to roll my own hack for such cases.
Well, if you are literally developing a model for recasting general XML in JSON, then you know the children of an entity should be a list because duplication os possible and order is signifcant. (Given the close relationships between XML and HTML and between JS and JSON, the obvious starting point for a general solution is to copy the HTML DOM, using only the properties.)
If you are trying not to reserialize XML generally but to solve the same problem as the original XML, then you probably aren’t doing it without a (logical) schema—you know what the object model is that you are trying to stuff into JSON, and you decide based on that.
I can implement a full, strict, compliant JSON parser in an afternoon, maybe even less time. It is simple enough to parse that you can even do it in pure C with relative ease. XML is a lot more complex and a lot of implementations skimped pretty hard on the details. I mean I have fond memories of tinyxml2, and if you take apart any app made in the 2000s you have a good chance of finding reference to it (or on Windows-only apps, MSXML3, or on Linux, libxml...) but it certainly let you do a lot of surprising things. I saw a lot of apps doing XML documents with multiple root nodes. And Apple's plist format is a nightmare. It's so easy to fuck up interpreting XML plist, that Apple did, and it lead to one of the more entertaining privilege escalation bugs in iOS history.
I have some fond memories, but I just don't miss XML. :)
I haven't seen any widely-adopted equivalent in JSON. I've seen some proposals floating around but none of them seem to have really taken off.
We already have this in JSON: add a hashmap key with a prefix. It's at least as robust provided tools do the sensible thing and ignore keys they don't care about. But as with XML, sometimes, they don't, or do, or something.
Maybe I'm paranoid, but I worry someone else will pick the same prefix as me. If you make the prefix something like a domain name, e.g example.com:myExtension, nobody else is going to use the same prefix assuming you own example.com. That avoids the risk, but it can be a lot of typing. Whereas, if the prefix is something short and obviously meaningful (e.g "doc:"), there is a risk someone else will use the same prefix in a conflicting way.
What I liked about XML namespaces is the indirection: the prefixes can be whatever you want, and then what makes them unique is the URIs they are defined to map to in each document.
The one point at which I think it didn't work very well, was when people started using prefixed names in attribute values. You can't tell whether "foo:bar" is a reference to the XML namespace with prefix "foo:", or some unrelated string of "foo:bar", without looking at the schema.
But none of that is really the problem - the problem is that the implementations and parsing are evidently sufficiently difficult that people just don't get them right - hence the hassle.
I would argue also that having indirection like this is just a negative all around - having to look elsewhere in the file to figure out what I'm looking at just creates problems, and in practice it doesn't look like this capability was ever really used - the only times I run into it are when I'm dealing with some vendor-specific implementation (that Python or Go or whatever can't handle so string-templating winds up being easier) and it turns out that what I need to have happen is to match the semantics of example XML exactly to get anything to work.
Which is really the point: the extra complexity in parsing means the probability you're dealing with a broken parser shoots through the roof, at which point you've lost any advantages. Whereas with JSON, the minimum bar is arrays and maps and the basic types work. Stay within those bounds, and whatever namespacing that happens will "just work".
If people use URLs, then DNS gives uniqueness to URLs. Of course each registrant has to enforce uniqueness within their registered domain – for a standards organisation or large software vendor, they often adopt a formal system (spreadsheet, database, naming convention, etc) for tracking which parts of the namespace under their domain name are reserved for which products/standards/etc. Of course, that relies on the vendor/organisation to do it properly – but if (e.g.) Microsoft were to create a mess by letting different Microsoft products use conflicting namespace URIs under microsoft.com, well that would be Microsoft's fault, and not the responsibility of any standard or technology to fix it.
(There is still one issue–what if the domain changes ownership? Some standards, for example ISO 19770, have tried to address this by constructing namespaces based on a domain name with its registration date, so if the domain later expires and is reused by a different organisation they won't clash since they'll have a new registration date.)
> the extra complexity in parsing means the probability you're dealing with a broken parser shoots through the roof
A lot of that is because namespaces were added to XML later, rather than being there from the start; they are effectively an optional feature. So then you have some parsers that support them, some parsers that don't, some parsers where it depends on a flag you have to set (which may default to true or false). I guess trying to add namespaces to JSON now would encounter the same problems. But if someone was to design a new serialisation format from scratch, and had namespace support in it from day 1, I don't think these issues would happen.
In practice not so much.
You will curse namespaces when you encounter some XML with multiple namespaces and your favorite parser starts choking on them.
Can you really? Doesn’t look like anyone else can: http://seriot.ch/parsing_json.php
There are are many parsers which perfectly parse every valid JSON document (like every Perl, Python and PHP parser and many others). They got non-perfect score because they accepted some JSON which standard says they should not have -- like a NaN value or a trailing comma.
While using such parsers can potentially cause problems -- perhaps because your data generator has a bug, and your not-strict-enough parser ignores this bug -- this happens very rarely in practice.
I did do this one actually in an afternoon:
https://github.com/pangbox/rugburn/blob/master/src/json.c
... but I will say that it is intentionally very limited in its API due to its intended use case and desired footprint. (And because it’s designed to compile with OpenWatcom 2 with no libc for only Win32, but those particular constraints are not very interesting for this.)
I would imagine if I did try, I would have a fighting chance at making something properly strict. But I admittedly don’t know how to handle recursion in a stackless manner.
Edit: specifically for C, it would be hard to do it properly unless I had access to an implementation of Clinger and Steele & White. Go would be easier since it has better floating point algorithms with strconv, but relying on C strtod/etc. is probably a bad idea due to variability. That having been said, maybe you could do Clinger in the same afternoon; I’d be worried about edge cases, but simply put, I haven’t tried.
I am not even a programmer by profession. Anyone that can write a recursive descent parser can write a JSON parser.