Why Dart should learn JSON while it's still young
2/14/2014 UPDATE 2: filed an issue for the DateTime->ISO8601 serialization.
2/2/2014 see UPDATE at the end
Remember how easy it was to learn your native language as a toddler? Of course you don't, and that's the point. Grammar and vocabulary somehow got hard-wired in your brain while you were very young, and pretty much all you had to do was listen and sleep. As we all know, it's much harder to learn another language later in life.
Here's one suggestion though I wanna make to Google's Dart team: teach your baby Dart to speak JSON, the web's data-interchange format, while it's still young.
"Wait a minute", you might say, "what hell are you talking about? Dart does already speak JSON. There's dart:convert, which allows you to decode and encode all day long."
Yes. But for a language designed as a new platform for scalable web app engineering, JSON shouldn't come as an afterthought, hidden somewhere in a library. JSON is everywhere on the web, and Dart should speak to you and listen to you in JSON like it's its native language. The Dart editor should be able to display a JSON serialization of anything the mouse pointer touches. Dart should breathe JSON. Let me give you an example:
A few weeks ago, I found it surprisingly hard to serialize a simple (plain-old) Dart object like
to this (very common) JSON representation
and ended up posting this question on Stackoverflow. It took me a bit by surprise when Google's Developer Advocate for Dart, Seth Ladd, replied that
Unfortunately, there's no universal JSON serialization of objects for all platforms.
Well, that's true. JSON has been designed as a data interchange format, which doesn't cover the platform and language specific serialization aspects. In fact, JSON is very lightweight by design. Side-note: I recommend reading RESTful Web APIs to learn more about emerging standards sitting on top of JSON, such as Collection+JSON.
However, as said: the web speaks JSON. Almost every RESTful API speaks JSON (well, a few still speak XML). The Twitter, Facebook, and Stack Exchange APIs speak JSON. Therefore, I think the simple serialization format above - even if not part of any formal standard - should become the default serialization of a Dart object.
So, just typing
var json = JSON.encode(customer);
should give me the the simple JSON representation of customer by default. As pointed out in the Stackoverflow question, I should not be required to explicitly implement toJson() or use a third-party library such as Alexander Tkachev exportable package (although I have to admit it's pretty neat).
There's one more thing - DateTime. Unfortunately, ECMA-404 doesn't standardize how to serialize dates. ISO 8601, however, does. Dart's DateTime class already "complies with a subset of ISO 8601" via its parse method..
So, here's another thing I wanna add to my suggestion: consider adapting ISO 8601 for a default JSON serialization of DateTime, so the following just works:
var dt = DateTime.parse("2014-01-26T11:38:17");
As of Dart 1.1.1, this will throw:
Converting object to an encodable object failed.
#0 _JsonStringifier.stringifyValue (dart:convert/json.dart:416)
#1 _JsonStringifier.stringify (dart:convert/json.dart:336)
#2 JsonEncoder.convert (dart:convert/json.dart:177)
#3 JsonCodec.encode (dart:convert/json.dart:106)
UPDATE - lots of very good feedback on Hacker News, here are some key points and my thoughts:
- Symbols (see skybrian's top rated comment; also pointed out by floitsch): the kind of default serialization I'm proposing requires preservation of symbols, which presents challenges around minimization (keep in mind that Dart code has to run in a browser), inheritance, and dynamic types. Great point, I haven't thought of that. A required class annotation such as @json (see zubspace's suggestion) might at least partially address these issues.
By the way: some other JSON serializers such as ServiceStack.Text (.NET) use reflection to serialize all member fields of an object unless the class is decorated with [DataContract], [DataMember] attributes in which case serialization becomes opt-in per member field. Dart could at least mimic the latter behavior.
- "JSON has no support for encoding new types into the serialization" (deathanatos' comment) - as pcwalton points out, this can be addressed by using Dart's (optional) static type information. DateTime is a very common type and should have a default serialization, and it should be ISO 8601. To be exact, RFC 3339 (which is a subset), as daurminator points out.
- "Can already be done" - for instance, floitsch points out that "It's extremely easy to get the behavior you want. [...] This way you pay the price when you want to, and don't force it on all users." - I certainly agree with the latter point if adding a default/out of the box JSON serialization does indeed add significant overhead, impacting all users including those which don't require it. On the flipside, if a cost-effective solution can be found - e.g. by providing a default JSON serialization via class annotations - I feel that it should be part of Dart's core and not up to individual developers to home-brew their own solution to a very common problem. In the particular case of DateTime, I'm pretty sure that adding a default JSON serialization now will increase interoperability between Dart-based services and sites in the future.