Hacker News new | ask | show | jobs
by sanitycheck 1173 days ago
I have huge respect for Doug Crockford, and I never imagined I would disagree with him.

However I think by now we've seen that a lot of that "unnecessary" XML complexity was not, in fact, entirely unnecessary. These days we use JSON for everything, but now we've got JSON Schema, Swagger/OpenAPI, Zod, etc etc. It's not really simpler and there's a lot of manual work - we might as well be using XML, XSD & SOAP/WSDL.

13 comments

XML is pretty awesome. As a 12 year old in 1998 I remember being enthralled with it and my young mind imagined a lot of possibilities. But alas, I had no real use for it until xhtml, but even then...As the years passed I learned to drive and get the heck off my computer for a few years.

It wasn't until about a decade later when I finally got to use XML "for real". At my academic publishing job. One of my first real projects was having a set of academics analyze documents in a web application I built. Prior to that they were analyzing them by hand, were converted to SGML somewhere in Korea, and we would use omnimark to move them to XML and eventually a library application.

The XML community, the one's who haven't retired or passed on, have been more welcoming of the competition too. They went from XML is everywhere, to being able to return JSON from an XSLT. I am in a small shop, and so I wear many hats. But I am always satisfied when I get to work with XML, or craft an xsl/xq script that does exactly what I need. Additionally, the community as a whole is very helpful, and a bit more grey. Meaning, they are less likely to fall for trends and bullshit.

A bit disjointed, but ,in short, XML is awesome. Now only if they would move Balisage back to Montreal. I'm no fan of DC or virtual conferences.

With XML, the complexity is the baseline, and it only goes up from there. With JSON, the complexity is just an option, the baseline is pretty simple. Also, good XML-tools are rare or expensive.
Baseline for XML would be a document that doesn't use schemas, namespaces, attributes, or any of the SGML legacy stuff like DTDs and PCDATA.

Such a document is essentially as simple as the equivalent JSON.

Even that is more complicated than JSON.
Care to elaborate?
Every key is written twice, for opening and closing. Keys can be duplicated, and in fact that's what you have to do if you want a simple list. There aren't numeric types, so you have to parse strings. It also looks horrible.

  <cds>
    <cd><title>Led Zeppelin II</title><artist>Led Zeppelin</artist><price>999</price></cd>
    <cd><title>La Brise<title><artist>Arax</artist><price>999</price></cd>
  </cds>
or

  <cds>
    <cd>
      <title>Led Zeppelin II</title>
      <artist>Led Zeppelin</artist>
      <price>999</price>
    </cd>
    <cd>
      <title>La Brise<title>
      <artist>Arax</artist>
      <price>999</price>
    </cd>
  </cds>
vs something like

  [
    {"title": "Led Zeppelin II", "artist": "Led Zeppelin", "price": 999},
    {"title": "La Brise", "artist": "Arax", "price": 999},
  ]
You can probably do better using XML attributes. But then you're using more features.
If we are complaining about the closing tags, might as well add that embedding newlines or quotes into JSON is less than pleasant.

Which is to say, this feels a touch of a non-issue. Yes, writing it by hand can get tedious, but that is true of any and every format. Is why you will almost certainly reach for other formats if doing a long list of data. And each and every one of them will fail for some form of input in ways that is frustrating.

Thanks. I get your point about the close element including the tag name - but that's the kind of detail I leave to the serialisation library, in the same way that the close scope token in json is different to the start scope token.

As for "looks horrible"... well yeah, I always feel that xml looks "spikey" somehow. But I've been programming in curly-brace languages for 30+ years and I still find json harder to read than xml: I think my brain tries to interpret it as code, not data. I find xml easier to read (even when its unformatted) precisely because the close-tokens kind of document what element they're closing.

Each to their own I guess. At least we're not stuck using ASN1.

And if someone is nice enough to stuff a NUL in the document, it all shatters.
Also this may just be the time in which I got into programming showing, but it seems like JSON encoding/decoding has been built into more languages than support for XML ever was. That's one less required dependency and thing to have to think about in many cases, like in Swift projects all I have to do is make sure my model structs/classes conform to Codable and I'm ready to hit endpoints.
That’s because writing a JSON parser is pretty straight forward with just a couple edge cases.

Writing a conformant XML parser is a HUGE undertaking comparison.

I could get most places to give me the time to write a JSON parser in whatever language of it didn’t have one. I couldn’t do that with XML.

Because of this, every common language (and most uncommon ones) has a JSON parser while XML parsers are less common (and fully conformant ones are even more rare).

Here to say this too. Compositional complexity is an advantage.

As a human in a repl, I appreciate the balance of readibility between XML which uses a larger set of syntactical characters, and YAML which uses fewer.

I also appreciate JSON's ontological simplicity over XML. This primarily boils down to the lack of attribute nodes and explicit difference between objects (lists of key-values) and arrays (lists of values).

> With XML, the complexity is the baseline, and it only goes up from there. With JSON, the complexity is just an option, the baseline is pretty simple.

Very well put. And we could lower the baseline substantially towards simplicity, even from JSON.

It's pretty clear that a lot of people think this way. Some even seriously try to figure out what such a baseline of simplicity would look like.

There are lots of simple indentation-based designs (similar to YAML) such as NestedText[0], Tree Notation[1], StrictYAML[2], or even @Kuyawa's Dixy[3] linked in this thread.

There seem to be less new ideas based around nested brackets, the way S-expressions are. Over the years, I have developed a few in this space, most notably Jevko[4]. If there ever will be another lowering of the simplicity baseline, I believe something like Jevko is the most sensible next step.

[0] https://nestedtext.org/en/stable/ [1] https://treenotation.org/ [2] https://hitchdev.com/strictyaml/ [3] https://news.ycombinator.com/item?id=35469643 [4] https://jevko.org/

I guess, it depends on how you define XML baseline. You can have a very simple XML with only bare tags. It will work just fine. Arguably, it's even simpler than JSON that way. A basic parser for that it probably not more complex than a JSON parser.

All the optional complexity that can go on top, though, is probably better specified for XML. Transformation is well defined for XML (XSLT) but not at all for JSON (I guess, you write your own code to manipulate native objects).

Schemas are basically a native feature for XML. Not so much for JSON.

All sorts of specialised vocabularies are defined for XML. A few are defined for JSON, too.

For a lot of XML you need to be able to support XML namespacing, and doing that adds a lot of complexity over the original pure XML.

At first XML namespacing sounds simple. Each tag and attribute will have an optional uri attached to it, no big deal right?

From reading through the specification one could be forgiven from assuming that the prefixes are just arbitrary mappings that a processor can ignore, or automatically remap to alternate prefixes.

For example, it is true that <abc:a xmlns:abc="https://example.com/xyz" xmlns:def="https://example.com/xyz"><def:b>5</def:b></abc:a> (notice both namespaces are the same url) is equivalent to: <a xmlns="https://example.com/xyz"><b>5</b></a>.

Unfortunately, the data model also allows for content to reference the namespaces by prefix, and therefore every general xml processor that supports namespaces must keep around an application accessible mapping from the prefixes to namespaces, as the application may need to be able to access that information to interpret attributes or content. The only exception to this would be if the general XML processor insisted on having schema information for every namespace it might come across. In that scenario it would be able to tell if an attribute value of "abc:b" is really a string literal, or a reference to a namespace identifier (QNAME data type), where the namespace is whatever the current "abc" prefix is bound to, and the identifier is "b".

But obviously we don't want to add full schema support for a simple implementation, so we need to keep the mapping information around, just in case the application needs it. We also cannot easily offer nice features like changing a document to use preferred prefixes for certain namespaces, unless we also keep any prefixes that are used in values that could be interpreted as QNAMES, just in case they actually are, but our processor does not know, because it has omitted schema support for simplicity (or perhaps it included schema support, but does not have a schema available for some namespace).

And that is just the complexity that stems from one fairly small quirk in how XML works.

You also have no idea if an element content needs to preserve whitespace or not if you don't know the schema, and don't happen to have an xml:whitespace attribute present. Thus if you want to re-indent arbitrary xml for readability safely you could end up with something like this:

    <abc
        ><def
            >5</def
        ></abc
    >
I understand what you're getting at but that is you choosing higher complexity baseline. Yes, it's a part of a standard but you can chose not to support it. No one said you have to support all of XML-verse in order to use it effectively in your particular application. The most common cases are usable without any of it. Look at most RSS/Atom feeds, XHTML, SVG. They all can get by with simple tags and and attributes.

I'm just not buying the argument that XML's complexity is somehow remediated in JSON. JSON becomes as horrible as XML when you bring it up to feature parity. And that's when there's a way to match features. Whatever people say about XSLT, it is powerful, reasonably well defined, and generic over all documents (even though complex). There's nothing like it for JSON I know of.

If we are going for simplicity, surely S-expressions wins? You can support structures similar to JSON or XML on top of it, but the baseline is simpler.
The new KiCad file formats are all S-expression based[0], except for the project files which are JSON IIRC. I think it works pretty well for representing a tree of typed objects textually. They don't even have any LISP connections. Haven't seen S-expressions used anywhere else, though.

[0]: https://dev-docs.kicad.org/en/file-formats/sexpr-intro/

I’d speculate that human minds and memories work much better with associative structures rather than sequenced ones. JSON draws a clean separation between these two and as a result has clearer syntax for the former.

ie, the benefits of simplicity have a limit.

I don’t write many APIs but every JSON schema I’ve created had been automatically generated by openapi tools. Even then I’ve found schemas of very little use, because everything gets validated on deserialization anyways. Client side validation usually already taken care of in practice because users should be serializing using the same type library that deserializes or reading the docs very thoroughly.

JSON is so much more ergonomic than XML as the lingua franca because I can actually read it. That being said I still have my share of problems with JSON.

That was the cause of the XML problems - everything was generated.

Me? Schemas are a requirement in areas where you need to integrate over different technology / with different implementations. JSON Schema is in those contexts a bit of a kids toy compared to what XML can do.

We’re using Prisma (https://prisma.io) schemas for a particular data exchange project we’re doing so that we can generate JSON schemas, SQLite schemas, PostgreSQL schemas, etc. We have even found a generator to create basic Elixir code from the Prisma schemas.

We’re not using anything else from Prisma, but if we had to implement something else in JS to talk to a database, that would be a contender for our database interface layer (there are only a couple of others that are even remotely usable, having suffered through the disaster of a Sequelize implementation). We’re more likely to use Elixir and Ecto.

Adding to the problems of generated schemas, Microsoft and Sun both had different views on how they should be generated. I bought into the promise of "build a wsdl" and you can get clients from .NET and Java. I lost all of that buy in. Hard.

I don't know that I can lay the blame on either one of them directly, mind. But the industry definitely suffered from the bad faith cooperation of those companies.

Microsoft, Sun, IBM, HP, Oracle et al explicitly made WDSL and related technologies not interoperate... and that is where JSON + universe has been a delight.
Totally fair. Not sure why I limited my memory to just the two companies.

I'm not clear on how JSON as a format has helped interaction. I'm reminded of like efforts to standardize how information is stored on pages. By and large, that ship sailed and sites that have remained somewhat stable have driven how we look for information on them. All without having to add new schema languages or tools.

I can still read the generated JSON.
> because everything gets validated on deserialization anyways

First, it really depends what you're deserializing with. There is a lot of code out there that just does JSON.parse and then starts accessing the data and then you have an "undefined" get passed deep into the call stack where maybe it explodes or maybe the program just misbehaves. So if you're using a language like JavaScript or Python, then a JSON schema can be used to validate input right away. Think of it like enforcing a pre-condition.

It's also useful in cases where JSON is being used for configuration files. At my company we have quite a few places where JSON files checked-in to a git repo are our source-of-truth which then get POST'ed to an API. We can enforce the schema of those files using pre-commit hooks so no one even wastes time opening a PR that will fail to POST to the API. The same JSON schema is also used by the API to ensure the POST'ed data is correct.

> First, it really depends what you're deserializing with. There is a lot of code out there that just does JSON.parse and then starts accessing the data and then you have an "undefined" get passed deep into the call stack where maybe it explodes or maybe the program just misbehaves.

I disagree, this example is just sloppy programming. Passing unvalidated data deep into a program is bad, I'm not arguing for that. What I'm saying is that you should be converting your unvalidated serialized data into a structured type right on the edge. Your data type/type system should __be__ your schema/validator.

> So if you're using a language like JavaScript or Python, then a JSON schema can be used to validate input right away. Think of it like enforcing a pre-condition.

This is what I do with python+pydantic:

    @dataclass
    class Foo:
        bar: int

    foo = Foo(**json.loads(json_buff))
I'm not the biggest fan of pydantic here because you'll have to handle an exception for invalid data instead of an Option or Result in a better type system. But w/e.

> It's also useful in cases where JSON is being used for configuration files. At my company we have quite a few places where JSON files checked-in to a git repo are our source-of-truth which then get POST'ed to an API. We can enforce the schema of those files using pre-commit hooks so no one even wastes time opening a PR that will fail to POST to the API. The same JSON schema is also used by the API to ensure the POST'ed data is correct.

You can easily do with serdes and a type library as well.

---

I guess schemas may be useful for crossing language boundaries, but you're going to need language specific types/objects at some point so why use schemas directly even then? (I think gRPC may have code gen tools for this purpose).

JSON is great, but I surely wish it supported comments. That's the nature of its failings: too minimal.
That depends on what you want it to be. For a data interchange format, having no comments is arguably a strength. For a config file format, having no comments is a big weakness.
Just do

  {
    "someSetting": true
    "comment": "TODO change to false when ready"
  }
Though really text-based protobufs are better for config.
Problems are that some tools will rewrite the file and reorder the "comment" away from what it's meant to comment on. Also might complain the "comment" item isn't expected there. I seem to remember package.json suffering from both of these under the control of npm.
Yeah it's definitely a limited solution, and I prefer that JSON be kept simple that way. Many package.json-adjacent configs like the Babel stuff can be in .js files, giving you comments and everything.
Many people use text format protobufs for config. It vaguely resembles yaml, and the schema is enforced by virtue of requiring a message definition in order to parse it.
This always bothered me. A coworker once suggested using fields ending in 'notes' to put in comments but I never really warmed up to that.
I have heard that too but it’s just a terrible idea.
Luckily a good number of parsers support extensions to JSON like comments and trailing comma's.
Comments are simple to parse, but preserving them on the dump is complex. I guess they were sacrificed for the simplicity.
They were excluded so people wouldn't use them to insert meta-processing instructions into the JSON doc.

In reality people insert those meta-processing instructions in other ways.

That’s a good point. It would be hard to read the JSON, modify it and then write back with comments.

But you still should have the option to at least ignore them while reading. That would make JSON config files so much better to work with.

You can use JSONC, which is JOSN with C style comments.
The ambiguity difference around lists alone makes JSON over XML compelling.

It is simpler than XML/XSD. Without the schema, you never know if a certain element should be treated as being part of a list or not. When interoperating with anything other than XML, that matters.

I dislike SOAP and avoid working with it when I can. However, the WSDL is an excellent part of SOAP that really makes it easier to work with. Teams tended to over engineer their APIs and all kinds of cruft would develop. I like the HTTP operations with REST.

I can remember hardcoding and manipulating a bunch of non-sense legacy fields just to get a ticket created via their SOAP enterprise service bus. Not to mention all the operations that made no clear sense.

soap may have taken liberties with http to get its work done (graphql: so what??) but it really felt like we reinvented the wheel. i was consuming massive wsdls in 2013/2014 and i consume massive open api specs in 2023. did anything actually improve?
Unless the implementation defines too many things as just "Object" and you're consuming from a stronger typed language... and the generated library doesn't give you anything resembling a real interface. I've used a dynamic language (Node) a few times to bridge such wsdl/soap services to consume from C# and similar.

Consuming SOAP/WSDL from languages other than the one it's published in isn't fun. Man, some of the PHP implementations were beyond horrible... well defined REST/RPC +_JSON is generally much easier in the end.

> I dislike SOAP and avoid working with it when I can.

I disagree. I think personal hygiene is very important for in-office coworking.

> I dislike SOAP and avoid working with it when I can.

Well, I'm about to take a shower now, and shame on you.

What I appreciate compared to xml is:

  - generic concepts like arrays and maps
  - lack of opportunity to invent names
Every xml schema is a potential DSL that reinvents things they might now.

Other than that it's true that the xml era was just addressing a lot of important stuff early, I guess it was only compatible with big corp mindset and not early web dynamic / fluid / small scale apps. (a bit like how PHP started to write PSR to avoir dynamic code / effects in libs .. formalization etc.

Every JSON schema is also a potential DSL that reinvents everything. Yes, there seems to be some convergence on things, but object arrays in XML aren’t really any more complex than object arrays in JSON — there just might be multiple ways to represent them.

For this JSON:

    {
      "part_numbers": [1, 2, 3, 4, 5]
    }
You have two main ways to represent these in XML:

    <!-- repetition = array -->
    <order>
      <part_number>1</part_number>
      <part_number>2</part_number>
      <part_number>3</part_number>
      <part_number>4</part_number>
      <part_number>5</part_number>
    </order>

    <!-- wrapped repetition -->
    <order>
      <part_numbers>
        <part_number>1</part_number>
        <part_number>2</part_number>
        <part_number>3</part_number>
        <part_number>4</part_number>
        <part_number>5</part_number>
      </part_numbers>
    </order>
Is this better than JSON? No, not particularly. But it’s no less clear than the JSON, and it compresses pretty well (it compresses better for larger documents, obviously).

The larger problem with XML is that the tooling is often lacking outside of Java and C#/.NET and none of the tooling is well-built for the sort of streaming manipulation that `jq` does (it exists, but IMO one of the least usable ideas from the XML camp is XSLT), and JSON support is pretty universal everywhere, even if the advanced things like JSONpath and JSON Schema aren’t.

I also think that there’s a problem when you have to choose between SAX and DOM parsing early in your process. Most JSON usage is the equivalent of using a DOM parser because the objects are expected to be relatively small, but many XML systems are built for much larger documents, and therefore need to parse the stream because the memory use otherwise would be unacceptable. The use of a JSON streaming parser is much rarer, IME.

Where XML shines is when you pass more complex data types than numbers and strings. If you repeated your example for an array of dates, as an example, strictly speaking you can't even generate the JSON. We'd first have to agree on what string representation of a date we want to use. For XML it's built into the spec.
In JSON the de facto standard for datetime is (because of JavaScript) very much the Unix msec timestamp (which is always in UTC) so while it's not hardcoded in spec you basically need to be an idiot not to do it like that, and removes one huge headache of XML dates which is timezones.
I don’t think that I’ve ever seen msec timestamps passed around because JSON numbers are floats, which means that there’s a limit to the precision available (which is to imply as well that currency amounts should be passed as decimal strings in JSON for safety as well).

Suggesting that msec timestamps resolves timezone issues is naïve at best, because anytime you are passing something that refers to a real time (that is, it is significant to humans) rather than an instant time (that is, it is something like an event log timestamp), you are dealing with time in a particular place, which has human impact — cultural, legal, linguistic.

Passing around timestamps as RFC3339 UTC strings with timezone names and offsets (much like one should be doing in databases) is what would be recommended for real (human) times.

Okay, so the point at which you need to adopt a schema language in toy examples is earlier with JSON, but in most practical cases you’ll want to do that in either JSON or XML (because, even if you are only using built-in types, you’ll still want to communicate the shape), so this objection is kind of meaningless.
Well, no. Because JSON & by extension OpenAPI lack a Date type you can't easily add validations about dates to those schemas. Like you can't say this particular date must be in the past in an OpenAPI spec because it has no concept of a date. The best you can do is a regex on the strings you call dates but that falls apart pretty quick.
> Like you can't say this particular date must be in the past in an OpenAPI spec because it has no concept of a date.

I don't get these types of arguments.

There's zero reason you can't write code that parses a date in an expected format (and throws an error if the date is formatted incorrectly) and then checks that the date is in the past.

Yes, it does mean you'll spend time writing more code (You know, the job you're being paid to do?), and it would be nice if your data format supported such automatic checking functionality out of the box, but to say "It can't be done!" is just plain silly.

I have literally never used any of these things.

The hate I have for XML is the high markup overhead. Anybody who has configured a trunk of the century product with XML config files knows what I mean; the screen is usually 2/3 XML tags, which means 1/3 closing tags, which add nothing semantically

> but now we've got JSON Schema, Swagger/OpenAPI, Zod, etc etc. It's not really simpler and there's a lot of manual work - we might as well be using XML, XSD & SOAP/WSDL.

Uh... do we? I've never used any of those. Plain JSON has always worked fine for me.

> but now we've got JSON Schema, Swagger/OpenAPI, Zod, etc etc.

You don't have to use any of those.

You don’t have to use anything for XML, either. The simplest XML document is almost indistinguishable from the simplest JSON document. Nothing in XML requires XML schemas or namespaces or anything else that is usually attributed to the complexities of XML.
I have to say that I was bit disappointed the first time I learned about JSON Schema. My immediate reaction was to wonder if they were trying to become XML.
OpenAPI is complex not because of JSON, but because it's a nearly complete description of http.
… and have proper comments.