I need to make a checksum from a JavaScript Object.
Unfortunately, there does not seem to be an easy way to accomplish this because of JavaScript's Object ordering. For example, take these Objects:
var obj1 = {type:"cake",quantity:0}
, obj2 = {quantity:0,type:"cake"};
I consider these Objects equal in data, and would like their checksums to be the same. I really don't care about the order of the Object just as long as the data in them is the same.
Alas, JSON.stringify
of both of them is actually not equal; as the only way to make a checksum of an Object is via its String representation, and the JSON.stringify
-ed representations are not equal, my checksums will not be equal!
One solution I have come up with is to recreate the Object based on a predefined schema, like so:
var schema = ["type","quantity"];
function sortify(obj,schema){
var n={};
for(i in schema)
n[schema[i]]=obj[schema[i]];
return n
}
Running JSON.stringify(sortify(obj1,schema))==JSON.stringify(sortify(obj2,schema))
will return true
... but at the price of creating a new Object and shuffling around data.
My other solution is to replace the JSON.stringify
method with one that picks keys from a predefined schema and stringifying their values, then joining them together.
The function reads:
function smarterStringify(obj,schema){
var s="";
for(i in schema)
s+=JSON.stringify(obj[schema[i]]);
return s
}
Ignoring the fact that this method doesn't return correct JSON (it's close enough as an example of what I'm trying to do), it is a massive improvement over the first one in speed (at least in my Chrome OS browser, you can check it yourself here: http://jsperf.com/sort-then-json-stringify-vs-smarter-stringify), and of course it makes the two Object String representations equal!
However, I was just wondering if I had missed something and there was a built-in method for something like this all along that didn't a) drive the JavaScript GC into a pathological case or b) do way too many String concatenations. I'd rather not do those.
for ... in
loops to iterate over arrays in JavaScript. Use a plainfor
loop with an index variable or use.forEach()
. – ScudJSON.stringify(obj,null,0)
. – Zanthoxylum