Native JSON Support in Opera

A while ago I was asked to do quality assurance on our upcoming JSON implementation. We support the JSON grammar and API specified in ECMAScript edition 5, ES5. ES5 was still being edited and changed while we were implementing and testing, but with the patient help of members of the ES-discuss list I got a test suite written and aligned with the upcoming spec. Stanislav - our JSON-implementor - had to be patient with me as tests were continually changing their pass conditions. For example, one day we were testing for the presence of a certain method, then the next day its absence!

At this point our implementation is considered ready for release, and I'm pretty excited about it - it was a pleasure to test, and Opera's native JSON support is going to be fast, strict, safe and standards-compliant. According to our tests our implementation is the fastest one at parsing -

Simple parse
Opera150 000 times/second
Safari127 000 times/second
IE41 000 times/second
Firefox37 500 times/second

though we're a bit slower than the others at serializing:

Simple stringify
Safari71 000 times/second
Firefox61 800 times/second
IE57 000 times/second
Opera55 800 times/second

..so there is a bit of work left on optimizing that. Keep in mind that this is with our existing JavaScript engine - the new Carakan engine gives JSON parsing a solid boost too!

Also, as you would expect from Opera, our JSON support is following the standard very closely. We are pretty standards-compliant, better than IE8 and Firefox 3.5, and on par with Safari 4.

Actually, make that almost standards-compliant. There are a couple of extremely odd edge case bugs that most likely won't cause you any problems - and there is one spec violation that we've decided to keep. Blame me for that decision, since I asked Stanislav to break his perfectly compliant implementation and ignore the specification here. Sincere apologies to Douglas "Mr. JSON" Crockford

Why violate the specification?

Let's take a step back: JSON has become hugely popular on the Web. It's a simplistic and flexible format for data exchange, parses quickly and integrates well with programming languages. It looks like (and is named after) a JavaScript object literal, so it's not surprising that JavaScript authors make good use of it, traditionally parsing it with eval(), loading it directly into a SCRIPT element, or using a custom parser written in JavaScript.

For certain use cases JSON is replacing XML for data exchange, mainly since it can be parsed faster. However, the languages have something in common: both have Draconian error handling.

Draconian error handling in JSON? Indeed, except it's nowhere near as controversial as XML's Draconianness, because JSON looks and feels like a programming language. We're all used to having to match our quotes and curly braces when programming. However, the spec grammar has a few additional constraints - a few points where correct JSON is different from and stricter than normal JavaScript source code, such as:

  • No hexadecimal number formats are allowed - {"number":0x1} is wrong!
  • Strings must be quoted with double quotes, not single - {"string": 'a string'} is wrong!
  • TAB characters may not appear inside strings - {"tab":"there is a tab -> <- here"} is wrong! The spec requires using \t instead of a literal TAB character.

The point of these constraints is to keep the syntax and JSON language simpler. However, when browsers start adding native JSON support, our implementations will enforce those constraints - something parsing JSON with eval() or SCRIPT tags never did. Hence, we're going to deal with potential compatibility issues with invalid JSON.

The spec rule Opera is going to violate for now is the one about not allowing tab characters inside strings. Currently all other browsers allow it (and if your browser fails this test case, it does too). I would like us to align with the spec, but I'm worried that we might break websites that do not escape tabs in their JSON data. If there are such "compatibility taxes" to be paid, I'd rather not have our users pay them.

As an example of what might break, I sent my GMail address an E-mail with a tab character in the subject field, and saw that GMail passed the tab around in its JSON data, unescaped. If GMail is using the browser's native JSON parsing and we follow the spec, somebody could then prevent your inbox from loading in Opera by sending you a message with tabs in the subject. And given the current browser implementations it would only break your GMail in Opera…

All browser developers discussing this on the es-discuss list have committed to aligning strictly with JSON grammar - so it should be only a matter of time before other major browsers do the right thing. When others pass the test we'll certainly follow. Meanwhile, enjoy faster and safer web applications thanks to a quality JSON implementation soon shipping in an Opera browser near you.