Why JSON Won ... And Is Good As It Is
I keep seeing developers complaining about different things with JSON protocol and don't get me wrong, I've been the first one trying to implement any sort of alternative starting from JSOMON and many others ... OK?
Well, after so many years of client/server development is not that I've given up on thinking "something could be better or different", is just that I have learned on my skin all reasons JSON is damn good as it is, and here just a few of these reasons.
Recursion is not a problem, is part of the serialization process to solve it, as well as classes together with protected and private properties. You can save almost any object within its state, even if this object won't be, as reference, the same you serialized .. and I would say: of course!
There are also two handy methods, __sleep and __wakeup, able to let you save an object state in a meaningful way and retrieve it back or perform some action during deserialization.
Are these things available in JSON ? Thanks gosh NO! JSON should not take care of recursive objects ... or better, it's freaking OK if it's not compatible 'cause recursion is a developer matter or issue, not a protocol one!
All JSON can do is to provide a way to intercept serialization so that any object with a
So, at the end of the day, JSON implementations might provide already a similar way to
Specially in .NET world most of documentation is written in a pseudo XML, can you imagine you bothering yourself to write such redundant markup language to write something often ignored by developers ? Would you like to have that "crap" as part of the data you are sending or receiving via JSON as part of that protocol? I personally don't ... thanks! 'cause I believe a transport protocol should be as compact as possible and without problems.
Here JSON wins once again 'cause it's compatible, with its few universal rules, with basically everything.
Lists, Arrays, Dictionaries, Objects, Maps, Hashes, call them as you want, these are the most used and cross language entities we all deal with on daily bases, together with booleans, strings, and numbers.
OK, OK, specially numbers are quite generic but you might admit that the world is still OK with a generic Int32 or Float32 number and with 64bits compatible environments, these numbers could be of a different type but only if you will never deal with 32 bits environments ... make you choice ... you want a truly big number? Go for it, and loose the possibility to "talk" with any other 32 bit env ... not a big deal if you own your data, kinda pointless memory and CPU consumption if you deserialize everything as 64 bits ... but I am pretty sure you know what you are doing so ... JSON is good in that case too.
Classes and namespaces issues, if you want, are there in any case.
The good part of JSON, once again, is the ability to intercept serialize and unserialize process so that if you like to send instances, rather than just objects, you can use all tools provided by the implementation, and I am showing in this case a JavaScript example;
Once we send this serialized version of our instance to any other client, the
Still in JavaScript, we can deserialize easily the string in such way:
Just imagine that
Confused ? Oh well, it's easier than it looks like ...
Once again, any other environment can understand what's traveling in therms of data, but we can recreate a proper instance whenever we want.
If you use weird objects and you expect your own thing to happen ... just use tools you have to intercept before and after JSON serialization and put there everything you want, otherwise just try to deal with things that any other language could understand or you risk to think JSON is your own protocol that's missing this or that, while you are probably, and simply, overcomplicating whatever you are doing.
Thanks for your patience
Well, after so many years of client/server development is not that I've given up on thinking "something could be better or different", is just that I have learned on my skin all reasons JSON is damn good as it is, and here just a few of these reasons.
Reliable Serialization ?
No, 'cause YAGNI. There are few serialization processes I know that kinda work as expected and since ever, PHP serialize is a good example.Recursion is not a problem, is part of the serialization process to solve it, as well as classes together with protected and private properties. You can save almost any object within its state, even if this object won't be, as reference, the same you serialized .. and I would say: of course!
There are also two handy methods, __sleep and __wakeup, able to let you save an object state in a meaningful way and retrieve it back or perform some action during deserialization.
Are these things available in JSON ? Thanks gosh NO! JSON should not take care of recursive objects ... or better, it's freaking OK if it's not compatible 'cause recursion is a developer matter or issue, not a protocol one!
All JSON can do is to provide a way to intercept serialization so that any object with a
.toJSON()
method can return it's own state and any time JSON.parse()
is performed, it could bring back, if truly necessary, its recursive property.So, at the end of the day, JSON implementations might provide already a similar way to
__sleep
and __wakeup
objects but it should be the JSON string owner, the service, the developer, to take care of these problems, and simply because ....Universal Compatibility
JSON is a protocol and as a protocol it should be as compatible as possible with all languages, not only those C like or others with similar comments ... there won't be comments ever in JSON, 'cause the moment you need comments, you don't need a transport protocol 'cause programming languages have always ignored developers comments ... and also, for compatibility reasons, not all programming languages would like to have//
or /* */
or even #
as inline or multiline comment ... why would they?Specially in .NET world most of documentation is written in a pseudo XML, can you imagine you bothering yourself to write such redundant markup language to write something often ignored by developers ? Would you like to have that "crap" as part of the data you are sending or receiving via JSON as part of that protocol? I personally don't ... thanks! 'cause I believe a transport protocol should be as compact as possible and without problems.
Here JSON wins once again 'cause it's compatible, with its few universal rules, with basically everything.
Different Environments
This is the best goal ever reached from a protocol, the fact that every programming language can represent somehow what JSON transports.Lists, Arrays, Dictionaries, Objects, Maps, Hashes, call them as you want, these are the most used and cross language entities we all deal with on daily bases, together with booleans, strings, and numbers.
OK, OK, specially numbers are quite generic but you might admit that the world is still OK with a generic Int32 or Float32 number and with 64bits compatible environments, these numbers could be of a different type but only if you will never deal with 32 bits environments ... make you choice ... you want a truly big number? Go for it, and loose the possibility to "talk" with any other 32 bit env ... not a big deal if you own your data, kinda pointless memory and CPU consumption if you deserialize everything as 64 bits ... but I am pretty sure you know what you are doing so ... JSON is good in that case too.
No Classes
And again thanks gosh! You don't want a protocol that deals with classes, trust me, 'cause you cannot write a class in all possible programming languages, can you? If you can, even in those programming languages where classes never existed 'cause classes are simply an abstract concept represented by the word "class" but representable in billion ways with other languages (e.g. via just objects in JavaScript).Classes and namespaces issues, if you want, are there in any case.
The good part of JSON, once again, is the ability to intercept serialize and unserialize process so that if you like to send instances, rather than just objects, you can use all tools provided by the implementation, and I am showing in this case a JavaScript example;
function MyClass() {
// doesn't matter what we do here
// for post purpose, we do something
this.initialized = true;
}
MyClass.prototype.toJSON = function () {
this.__class__ = "window.MyClass";
return this;
};
var myClassObject = JSON.stringify(new MyClass);
// "{"initialized":true,"__class__":"window.MyClass"}"
Once we send this serialized version of our instance to any other client, the
.__class__
property could be ignored or simply used to understand what kind of object was it.Still in JavaScript, we can deserialize easily the string in such way:
function myReviver(key, value) {
if (!key) {
var instance = myReviver.instance;
delete instance.__class__;
delete myReviver.instance;
return instance;
}
if (key == "__class__") {
myReviver.instance = myReviver.createInstance(
this, this.__class__
);
}
return value;
}
myReviver.createInstance = "__proto__" in {} ?
function (obj, className) {
obj.__proto__ = myReviver.getPrototype(className);
return obj;
} :
function(Bridge) {
return function (obj, className) {
Bridge.prototype = myReviver.getPrototype(className);
return new Bridge(obj);
};
}(function(obj){
for (var key in obj) this[key] = obj[key];
})
;
myReviver.getPrototype = function (global) {
return function (className) {
for (var
Class = global,
nmsp = className.split("."),
i = 0; i < nmsp.length; i++
) {
// simply throws errors if does not exists
Class = Class[nmsp[i]];
}
return Class.prototype;
};
}(this);
JSON.parse(myClassObject, myReviver) instanceof MyClass;
// true
Just imagine that
__class__
could be any property name, prefixed as @class
could be, or with your own namespace value @my.name.Space
... so no conflicts if more than a JSON user is performing same operations, isn't it?Simulating __wakeup Call
Since last example is about__sleep
, at least in JavaScript easily implemented through .toJSON()
method, you might decide to implement a __wakeup
mechanism and here what you could add in the proposed revival method:
function myReviver(key, value) {
if (!key) {
var instance = myReviver.instance;
delete instance.__class__;
delete myReviver.instance;
// this is basically last call before the return
// if __wakeup was set during serialization
if (instance.__wakeup) {
// we can remove the prototype shadowing
delete instance.__wakeup;
// and invoke it
instance.__wakeup();
}
return instance;
}
if (key == "__class__") {
myReviver.instance = myReviver.createInstance(
this, this.__class__
);
}
return value;
}
Confused ? Oh well, it's easier than it looks like ...
// JSON cannot bring functions
// a prototype can have methods, of course!
MyClass.prototype.__wakeup = function () {
// do what you need to do here
alert("Good Morning!");
};
// slightly modified toJSON method
MyClass.prototype.toJSON = function () {
this.__class__ = "window.MyClass";
// add __wakeup own property
this.__wakeup = true;
return this;
};
Once again, any other environment can understand what's traveling in therms of data, but we can recreate a proper instance whenever we want.
How To Serialize
This is a good question you should ask yourself. Do you want to obtain exactly the same object once unserialized? Is that important for the purpose of your application? Yes? Follow my examples ... no? Don't bother, the less you preprocess in both serializing and unserializing objects, the faster, easier, slimmer, will be the data.If you use weird objects and you expect your own thing to happen ... just use tools you have to intercept before and after JSON serialization and put there everything you want, otherwise just try to deal with things that any other language could understand or you risk to think JSON is your own protocol that's missing this or that, while you are probably, and simply, overcomplicating whatever you are doing.
You Own Your Logic
Last chapter simply demonstrates that with a tiny effort we can achieve basically everything we want to ... and the cool part is that JSON, as it is, does not limit us to create more complex structures to pass once stringified or recreate once parsed and this is the beauty of this protocol so please, if you think there's something missing, think twice before proposing yet another JSON alternative: it works, everywhere, properly, and it's a protocol, not a JS protocol, not a X language protocol ... just, a bloody, protocol!Thanks for your patience
Comments
Post a Comment