* It's inefficient compared to schema-based formats like Protobuf - you have to encode key names again and again.
* It's inefficient compared to binary equivalent formats like CBOR - both in space and speed.
* It's less reliable than explicit schema-based formats because it can't be validated (yes I know about JSON-Schema, nobody uses it). You essentially end up with an implicit schema that everyone has to recreate themselves from the documentation - especially if using statically typed languages.
* It's a pain to use from statically typed languages. You have to write the schema in your language, whereas with things like Protobuf it will generate the code for you.
* It doesn't have a proper type for arbitrary binary data. Most people (but not all!) encode it as a base64 string which is not very efficient and not actually a different type to a string, so again you rely on the implicit schema.
* Maps can only have strings as their key type.
* Minor annoyance, but trailing commas would be nice!
* Its number type is not well specified. E.g. does it support uint64?
"Human readable" is overrated. CBOR and similar formats can easily be inspected by humans just by converting them to JSON. The Smile format even starts with a :) smilie as its magic number to make it easily recognisable.
Would you recommend not using compression or encryption on HTTP requests because it stops them being human readable?
It's a wasteful, textual format derived from a programming language vomited forth in under a week. It has asinine integer characteristics for no good reason; it's not a random-access format; validating it is even more work; hash table keys that appear multiple times, instead of being in error, instead overwrite each other, defeating most any kind of optimization; it is thus wildly inefficient to manipulate, as manipulating it correctly in all cases requires full and comprehensive parsing with checking. It is an asinine ''format''.
>It's a text format that can be inspected by humans, unlike binary formats.
Even then, there are much better textual formats that could be used, but I'm of the opinion that numerical (binary) formats are strictly superior, especially as they're used increasingly often. It's better to have good tools that will provide a human-readable representation, rather than pretend a single, inefficient representation for both man and machine is somehow the best option.
>(Maybe IMAP is a text format too, so this isn't an advantage inherently) And JMAP may have better semantics than IMAP, and there's nothing inherently wrong with JSON (other than edge cases).
Computer programs written by anyone competent are built around edge cases; that's much of what any reliable program is, accounting for edge cases. To disregarded edge cases, of which there are many in JSON, speaks to me that you have little concern for writing software correctly, but I imagine you'd deny this, as who doesn't want to write correct software? Simply understand that using a format with so many edge cases and other defects as JSON is foolhardy for much of anything.
I don't think that's true. The behavior with multiple keys is not defined. A JSON reader can choose to do whatever it wants (error, use first, use last, use all, etc). An interoperable JSON writer should never output duplicate keys.
The relevant RFC is 8259, which neither explicitly allows nor prohibits duplicate keys. Instead it says:
> An object whose names are all unique is interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings. When the names within an object are not unique, the behavior of software that receives such an object is unpredictable. Many implementations report the last name/value pair only. Other implementations report an error or fail to parse the object, and some implementations report all of the name/value pairs, including duplicates.
That isn't a prohibition on duplicate keys, it's just a warning on what will happen in practice if you try to do that.
> Objects in I-JSON messages MUST NOT have members with duplicate names.
(Does JMAP require validating that the input is valid I-JSON? Or does it just say that a JMAP endpoint is allowed to assume it's I-JSON, but doesn't need to validate it?)
(Related: Postel’s law is wrong. See https://tools.ietf.org/html/draft-iab-protocol-maintenance-0... for some explanation.)
https://tools.ietf.org/html/rfc6868
Which is the kind of horror case of trying to do everything with clever little pieces of micro-format.
Now, the argument between XML and JSON is less of a big deal, except XML gets wishy-washy with whitespace in some ways which frustrate me. JSON number handling is screwy, it's true. I'd be tempted by CBOR if there were no other considerations - and I'd love to write a JMAP-over-CBOR or JMAP-over-ASN.1 or whatever at some point.
But you can very easily structure non-binary data in and out of JSON reliably, and everyone can get a parser which works. That's a big win. It's fine to disregard edge cases if you stay away from the edges - for example if you're serialising integers between 0 and 1000 then the fact that your datatype isn't 256 bit clean isn't a big deal. Same way you can use Newtonian physics when dealing with sprinters - but I don't think that race organisers have little concern for running a race correctly because they don't factor in relativity.
So we kept JMAP in the safe subset of JSON, because it's the best format for a whole lot of other reasons.
If, for example, you try sending a request with duplicated keys in an object, the JMAP server will reject your request with the urn:ietf:params:jmap:error:notJSON error.
I'm working on a chiptune music composing program (FamiTracker), which saves projects in a binary format designed by my predecessor. I once repaired a corrupted file for someone else. It's borderline impossible to repair binary formats by hand, since inspecting the data on-disk provides no clues about the structure, which I don't know since I didn't write the program. I ended up merging the corrupted file and an older backup in Audacity (an audio editor) by sliding the two files back and forth relative to each other, because hex editors are awful at visualizing and aligning binary files (whereas diff tools are good at visualizing and aligning text files).
Additionally, the on-disk layout changes between versions, and the reader code is a mess of branching between different on-disk layouts based on the version number.
Additionally, it's impossible to check in your music project (binary blob) into Git, then get a meaningful diff between different versions, let alone being able to merge changes made in 2 branches. (Yes, I use Git for music. It's actually useful.)
Needless to say, I'm using a text format if I ever write a replacement. A text format may have trouble encoding binary blobs, but I don't like the idea of "transcoding .wav into binary files, and throwing away the parameters used". I'm more inclined to just use pointers to on-disk .wav, and store all metadata needed to reproduce the binary blobs, and possibly cache the binary blobs in base64 for speed and convenience.
That's interesting. If you're interested in discussing that more at some point, email me. Now, I've designed a numerical format for metadata involving machine code programs and, while I've not written this piece yet, an important aspect of this will be a repairing tool. The only reason a textual format would be easier to repair by hand is because you can use a text editor and it's more redundant. Now, good design is another quality; ideally, a numerical format would lack holes that are invalid states and wouldn't be riddled with pointers or other things if feasible; it varies based on what you're doing, though.
I ended up merging the corrupted file and an older backup in Audacity (an audio editor) by sliding the two files back and forth relative to each other, because hex editors are awful at visualizing and aligning binary files (whereas diff tools are good at visualizing and aligning text files).
That's again a simple matter of tooling that could be corrected.
Additionally, the on-disk layout changes between versions, and the reader code is a mess of branching between different on-disk layouts based on the version number.
A runaway format revision like that isn't ideal, I can agree. You can get the same mess with textual formats, however.
Additionally, it's impossible to check in your music project (binary blob) into Git, then get a meaningful diff between different versions, let alone being able to merge changes made in 2 branches. (Yes, I use Git for music. It's actually useful.)
I don't use git at all, so this is another difference between us. I'm largely of the opinion that the focus on textual formats for UNIX-likes was due to sloth more than anything, as there's generally a lack of coherency between /etc/fstab to /etc/passwd and so on; I believe the focus was largely due to the advantage of ostensibly generic tooling, but reading or writing a configuration in a text editor, with the manual handy, and getting errors and other things upon loading it is worse than having a tool write it for you and show it to you at a high-level.
Needless to say, I'm using a text format if I ever write a replacement. A text format may have trouble encoding binary blobs, but I don't like the idea of "transcoding .wav into binary files, and throwing away the parameters used". I'm more inclined to just use pointers to on-disk .wav, and store all metadata needed to reproduce the binary blobs, and possibly cache the binary blobs in base64 for speed and convenience.
I don't know the details of what you're dealing with, but again, if you're interested, email me and I can perhaps work on a repair tool or help design a replacement numerical format that will be easier to manipulate.
Actually, IMAP is a binary format that looks like a text format. This distinction is extremely important when you want to make a reliable Email client. There are also multiple ways of encoding text within it, that you need to keep track of.
Personally, I wish they used a structured binary encoding. This becomes especially important when data size efficiency actually matters. With something like protobuf, you can even have the parser for it generated for you. (However, I have worked with binary formats that are more loosely structured.)
Of course I am a fan of well defined and strongly typed formats.
- It is way too easy to change the schema and wreak havoc with downstream users.
- Some libraries will encode empty strings as null for instance, some as empty strings. Some will have empty objects, some null. Switch some configuration, change your serializer, ORM or anything that touches your data. Everything will work perfectly in your code, but json output can change and you will again break your downstream users.
If you are designing an API, use protocol buffers. Json maybe as an optional output/input to your service. Keep it as a discouraged dirty optional feature and you will save yourself a whole lot of debugging and time wasting.