3 ms·
> Canonical S-expressions would have been far preferable, but for whatever reason the world didn’t go that way. I feel like not understanding why JSON won out
by cortesoft 1y ago
> Canonical S-expressions would have been far preferable, but for whatever reason the world didn’t go that way.
I feel like not understanding why JSON won out is being intentionally obtuse. JSON can easily be hand written, edited, and read for most data. Canonical S-expressions are not as easy to read and much harder to write by hand; having to prefix every atom with a length makes is very tedious to write by hand. If you have a JSON object you want to hand edit, you can just type... for an Canonical S-expression, you have to count how many characters you are typing/deleting, and then update the prefix.
You might not think the ability to hand generate, read, and edit is important, but I am pretty sure that is a big reason JSON has won in the end.
Oh, and the Ruby JSON parser handles that large number just fine.
- eadmund 1y ago> I feel like not understanding why JSON won out is being intentionally obtuse. I didn’t feel like my comment was the right place to shill for an alternative, but rather to complain about JSON. But since you raise it. > JSON can easily be hand written, edited, and read for most data. So can canonical S-expressions! > Canonical S-expressions are not as easy to read and much harder to write by hand; having to prefix every atom with a length makes is very tedious to write by hand. Which is why the advanced representation exists. I contend that this: (urn:ietf:params:acme:error:malformed (detail "Some of the identifiers requested were rejected") (subproblems ((urn:ietf:params:acme:error:malformed (detail "Invalid underscore in DNS name \"_example.org\"") (identifier (dns _example.org))) (urn:ietf:params:acme:error:rejectedIdentifier (detail "This CA will not issue for \"example.net\"") (identifier (dns example.net)))))) is far easier to read than this (the first JSON in RFC 8555): { "type": "urn:ietf:params:acme:error:malformed", "detail": "Some of the identifiers requested were rejected", "subproblems": [ { "type": "urn:ietf:params:acme:error:malformed", "detail": "Invalid underscore in DNS name \"_example.org\"", "identifier": { "type": "dns", "value": "_example.org" } }, { "type": "urn:ietf:params:acme:error:rejectedIdentifier", "detail": "This CA will not issue for \"example.net\"", "identifier": { "type": "dns", "value": "example.net" } } ] } > for an Canonical S-expression, you have to count how many characters you are typing/deleting, and then update the prefix. As you can see, no you do not.
- eximius 1y agoFor you, perhaps. For me, the former is denser, but crossing into a "too dense" region. The JSON has indentation which is easy on my poor brain. Also, it's nice to differentiate between lists and objects. But, I mean, they're basically isomorphic with like 2 things exchanges ({} and [] instead of (); implicit vs explicit keys/types).
- josephg 1y agoYeah. I don’t even blame S-expressions. I think I’ve just been exposed to so much json at this point that my visual system has its own crappy json parser for pretty-printed json. S expressions may well be better. But I don’t think S expressions are better enough to be able to overcome json’s inertia.
- em-bee 1y agoeven as a fan of s-expressions (see my other comment), i have to agree. but the problem here is the formatting. for starters, i would write the s-expression example as: (urn:ietf:params:acme:error:malformed (detail "Some of the identifiers requested were rejected") (subproblems ((urn:ietf:params:acme:error:malformed (detail "Invalid underscore in DNS name \"_example.org\"") (identifier (dns _example.org))) (urn:ietf:params:acme:error:rejectedIdentifier (detail "This CA will not issue for \"example.net\"") (identifier (dns example.net)))))) the alignment of the values makes them easier to pick out and gives a visual structure but, i would also argue that the two examples are not equivalent. what is explicitly specified as "type" and "value" in the json data, is implied in the s-expression data. either format is fine, but it would be better to compare like for like: an s-expression equivalent for the json example would look like this: ((type urn:ietf:params:acme:error:malformed) (detail "Some of the identifiers requested were rejected) (subproblems ((type urn:ietf:params:acme:error:malformed) (detail "Invalid underscore in DNS name \"_example.org\"") (identifier (type dns) (value _example.org))) ((type urn:ietf:params:acme:error:rejectedIdentifier) (detail "This CA will not issue for \"example.net\"") (identifier (type dns) (value example.net))))) or the reverse, a json equivalent for the s-expression example: { "urn:ietf:params:acme:error:malformed": { "detail": "Some of the identifiers requested were rejected", "subproblems": [ "urn:ietf:params:acme:error:malformed": { "detail": "Invalid underscore in DNS name \"_example.org\"", "identifier": { "dns": "_example.org" } }, "urn:ietf:params:acme:error:rejectedIdentifier" { "detail": "This CA will not issue for \"example.net\"", "identifier": { "dns": "example.net" } } ] } } a lot of the readability depends on the formatting. we could format the json example more dense: {"urn:ietf:params:acme:error:malformed": { "detail": "Some of the identifiers requested were rejected", "subproblems": [ "urn:ietf:params:acme:error:malformed": { "detail": "Invalid underscore in DNS name \"_example.org\"", "identifier": { "dns": "_example.org" }}, "urn:ietf:params:acme:error:rejectedIdentifier": { "detail": "This CA will not issue for \"example.net\"", "identifier": { "dns": "example.net" }}]}} doing that shows that the main problem that makes json harder to read is the quotes around strings. because if we spread out the s-expression example: (urn:ietf:params:acme:error:malformed (detail "Some of the identifiers requested were rejected") (subproblems ((urn:ietf:params:acme:error:malformed (detail "Invalid underscore in DNS name \"_example.org\"") (identifier (dns _example.org) ) ) (urn:ietf:params:acme:error:rejectedIdentifier (detail "This CA will not issue for \"example.net\"") (identifier (dns example.net) ) ) ) ) ) that doesn't add much to the readability. since, again, the primary win in readability comes from removing the quotes.
- pharrington 1y agoThe entire reason ACME exists is because you are never writing or reading the CSR by hand. So of course, ACME is based around a format whose entire reason d'etre is being written and read by hand. It's weird.
- thayne 1y agoThe reason json is a good format for ACME isn't that it is easy to read and write by hand[1], but that most languages have at least one decent json implementation available, so it is easier to implement clients in many different languages. [1]: although being easy to read by humans is an advantage when debugging why something isn't working.
- motorest 1y ago> I feel like not understanding why JSON won out is being intentionally obtuse. JSON can easily be hand written, edited, and read for most data. You are going way out of your way to try to come up with ways to rationalize why JSON was a success. The ugly truth is far simpler than what you're trying to sell: it was valid JavaScript. JavaScript WebApps could parse JSON with a call to eval(). No deserialization madness like XML, no need to import a parser. Just fetch a file, pass it to eval(), and you're done.
- amne 1y agoit's in the name after all: [j]ava[s]cript [o]bject [n]otation
- jaapz 1y agoBut also, all the other reasons written by the person you replied to
- motorest 1y ago> But also, all the other reasons written by the person you replied to Not really. JSON's mass adoption is tied to JavaScript's mass adoption, where sheer convenience and practicality dictates it's whole history most of the current state. Sending JavaScript fragments from the backend is a technique that didn't really stopped being used just because someone rolled out a JSON parser. I think some people feel compelled to retroactively make this whole thing more refined and elegant because for some the ugly truth is hard to swallow.
- nextaccountic 1y agoIn other words, the thing that made JSON initially succeed was also a giant security hole
- motorest 1y ago> In other words, the thing that made JSON initially succeed was also a giant security hole Perhaps, but it's not a major concern when you control both the JavaScript frontend and whatever backend it consumes. In fact, arguably this technique is still pretty much in use today with the way WebApps get a hold of CSRF tokens. In this scenario security is a lesser concern than, say, input validation.
- beeflet 1y agoyou can use a program to convert between s-expressions and a more readable format. In a world where canonical s-expressions rule, this "more readable format" would probably be an ordinary s-expression
- lisper 1y ago> Canonical S-expressions are not as easy to read and much harder to write by hand You don't do that, any more than you read or write machine code in binary. You read and write regular S-expressions (or assembly code) and you translate that into and out of canonical S expressions (or machine code) with a tool (an assembler/disassembler).
- cortesoft 1y agoI have written by hand and read JSON hundreds of times. You can tell me I shouldn’t, but I am telling you I do. Messing around with an API with curl, tweaking a request object slightly for testing something, etc. Reading happens even more times. I am constantly printing out API responses when I am coding, verifying what I am seeing matches what I am expecting, or trying to get an idea of the structure of something. Sure, you can tell me I shouldn’t do this and I should just read a spec, but in my experience it is often much faster just to read the JSON directly. Sometimes the spec is outdated, just plain wrong, or doesn’t exist. Being able to read the JSON is a regular part of my day.
- lisper 1y agoI think there may be a terminological disconnect here. S-expressions and canonical S-expressions are not the same thing. S-expressions (non-canonical) are a comparable to JSON, intended to be read and written by humans, and actually much easier to read and write than JSON because it uses less punctuation. https://en.wikipedia.org/wiki/S-expression https://en.wikipedia.org/wiki/S-expression A canonical S-expression is a binary format, intended to be both generated and parsed by machines, not humans: https://en.wikipedia.org/wiki/Canonical_S-expressions https://en.wikipedia.org/wiki/Canonical_S-expressions