JSON vs XML: Attributes, Arrays, Types and Comments
JSON writes data as typed values in objects and arrays, and XML marks up a document as a tree of named elements. A conversion between them has to decide what each one has no way to say.
What is the difference between JSON and XML?
JSON is a syntax for values and XML is a markup language for documents. JSON has types and arrays and nothing else; XML has elements, attributes, comments and namespaces, and every value it holds is character data.
RFC 8259 defines JSON as a text format for the serialization of structured data, derived from the object literals of JavaScript, and ECMA-404 is intended to describe the same grammar.
XML 1.0 is a W3C Recommendation for describing a document's logical structure as a tree of elements: a well-formed document has exactly one root element, and every other element sits wholly inside another.
| Property | JSON | XML |
|---|---|---|
| Defined by | RFC 8259, Standards Track, December 2017; also ECMA-404 | W3C Recommendation, Extensible Markup Language (XML) 1.0 |
| Media type | application/json | application/xml and text/xml |
| Structure | objects and arrays, nested to any depth | a tree of elements, each carrying attributes and content |
| Top level | any single value: an object, an array, a string, a number, a boolean or null | exactly one root element |
| Types | string, number, boolean, null, object, array | none in XML 1.0 itself - every attribute value and text node is character data |
| Lists | ordered arrays, whose values need not share a type | none; sibling elements that share a name stand in for one |
| Attributes | none; an object holds name/value members only | name-value pairs in a start tag, each name at most once and in no significant order |
| Comments | none - the grammar has no comment production | <!-- ... --> |
| Namespaces | none; a member name is only a string | a URI reference, bound to a prefix by an xmlns attribute |
| Encoding | UTF-8 | every processor must accept UTF-8 and UTF-16; an encoding declaration brings in others |
Every row where the two columns disagree is a decision a converter has to take, and the sections below take them in turn, using what the converters on this site write. Size follows from the syntax: an XML element with content repeats its name in its end tag, and JSON writes each name once.
<part sku="A-10"><name>Bolt</name><qty>25</qty></part> is 54 bytes, and the same record as JSON, {"part":{"@sku":"A-10","name":"Bolt","qty":25}}, is 47 bytes.
Attributes become members with a marker
An XML attribute may appear at most once per element and the order of attributes in a start tag carries no meaning; a child element may repeat any number of times and its order does carry meaning. An attribute value is always text, while an element can hold text, other elements, or both.
JSON has one kind of container for both, so an XML to JSON conversion has to choose. Attributes and child elements collapse into the same kind of member, a single child element gives no way to tell one value from a one-element array, and mixed content - text interleaved with child elements - has no JSON shape at all.
So something in the JSON has to record which members were attributes.
The converters on this site write an XML attribute as a JSON member whose name starts with @, and write a member named that way back as an attribute.
<part sku="A-10"><name>Bolt</name></part> becomes {"part":{"@sku":"A-10","name":"Bolt"}}.
The @ is this site's convention, not part of either format, and another converter may mark attributes differently. To go the other way, turn a JSON document into XML and a member named with @ becomes an attribute of its element again.
Repeated elements become arrays, and one element does not
Siblings that share a name read naturally as a list, and a child element that appears once is the case the file cannot settle: one value, or a list of one. From the JSON side the gap runs the other way. XML has no array, so each element of a list needs an element of its own, and something has to name it.
{"tags":["m6","steel"]} becomes <root><tags><item>m6</item><item>steel</item></tags></root>, and reading that back gives {"root":{"tags":{"item":["m6","steel"]}}}.
The round trip does not come back as it went in. The item elements and the root wrapper both survive, so the list returns one level deeper, inside an object. When you read an XML file into JSON, a child element that appears once is flagged so you can see where that choice was made.
Numbers and booleans lose their type
JSON tells 25 from "25" and true from "true". XML 1.0 has no type set, so a number and a boolean become character data, and nothing in the XML records what they were.
{"qty":25,"inStock":true} becomes <root><qty>25</qty><inStock>true</inStock></root>, and reading that back gives {"root":{"qty":"25","inStock":"true"}}.
Reading that XML back, the converter cannot tell a number written as characters from text that happens to look like one, so both come back as strings.
A JSON null becomes an empty element, and so does an empty string, so both come back from XML as null.
Namespaces and comments have no JSON form
Namespaces in XML 1.0 identifies a namespace by a URI reference and declares it with an attribute named xmlns or starting xmlns:, and a prefix is only a placeholder for that URI.
<part xmlns:inv="https://example.org/inventory"><inv:sku>A-10</inv:sku></part> becomes {"part":{"@xmlns:inv":"https://example.org/inventory","inv:sku":"A-10"}}.
JSON has no namespaces, so the prefixed name travels as it was written and the declaration becomes an ordinary member. Two files that bind different prefixes to the same URI mean the same thing in XML and give different keys in JSON.
XML 1.0 says a comment is not part of the document's character data, and a processor need not pass its text on to an application.
JSON has no comments and no trailing commas because RFC 8259's grammar has no production for either. A comma may appear only between two members of an object or two elements of an array, so a comma before the closing brace or bracket makes the text invalid.
A comment in the XML therefore has nowhere to go. The same grammar rule is why JSON rejects a comment typed in by hand.
The XML to JSON converter on this site drops a comment and reports that it did.
When should you use XML instead of JSON?
When the content is a document rather than a set of values. The deciding cases are the rows above where XML can say something JSON cannot:
- Prose with markup inside it, such as a sentence with one phrase tagged. That is mixed content, and it has no JSON shape.
- Metadata that belongs beside the content, as attributes, rather than inside it.
- Comments that have to travel with the file.
- Names from more than one vocabulary in one document, kept apart by namespaces.
JSON fits when the content is values: numbers and booleans that must stay numbers and booleans, lists that must stay lists, and no root element or item tag to invent.
Frequently Asked Questions
Is JSON replacing XML?
Neither specification replaces the other. RFC 8259 is an IETF Standards Track document and XML 1.0 is a W3C Recommendation, and they describe different things: JSON describes values, and XML describes marked-up documents.
What are the disadvantages of using JSON?
It has no comments and no attributes, and there is no date type, so a note, a piece of metadata or a date travels as an ordinary member or string. RFC 8259 lets a parser set its own limits on range and precision, so very large numbers may not survive.
Which is smaller, JSON or XML?
It depends on the record, but XML repeats each element name in its end tag and JSON writes each name once. The three-field part record on this page is 54 bytes as XML and 47 bytes as JSON.
Once you know which way the file is going, the converter for each format pair is on the hub.