DEV Community

Discussion on: The secret power of JSON stringify

Collapse
 
sidvishnoi profile image
Sid Vishnoi • • Edited

Regarding the second items white list (array) argument:
We can use it to create a simple object hashing function (similar to object-hash, but with limitation of maximum object depth 1). The important thing is, JSON.stringify(obj) may not follow property order, which matters when the serialization is input for hashing/checksum. Instead we can pass Object.keys(obj).sort() as the 2nd argument, and the JSON will be stringified in that property order only.

function objectHash(obj: object): string {
  const str = JSON.stringify(obj, Object.keys(obj).sort());
  return createHash('sha1').update(str).digest('hex');
}
Enter fullscreen mode Exit fullscreen mode

View code snippet for client-side at GitHub
View code snippet for Node.js at GitHub and tests

Collapse
 
thirdy profile image
APerfectCircle •

Nice to know. However, being a java developer, this brings me to think that this should be a built-in functionality. Doesn't plain JS have hashing function for all it's objects?

Collapse
 
sidvishnoi profile image
Sid Vishnoi •

No. JS doesn't expose any hashing function for any of its supported types.

Collapse
 
neilcodes profile image
Neil •

This is kind of horrifying and I love it.

Collapse
 
sonicoder profile image
Gábor Soós •

Wow, didn't know it. Nice snippet! I always learn something new.

Collapse
 
getclibu profile image
Neville Franks • • Edited

I'd been looking everywhere to find a simple way to get JSON.stringify() to output items in a specific order. You post provided exactly what I needed to do what I wanted.

Unfortunately upon reading the JSON.stringify() docs I can't find any information on using a replacer array to set keys order. Only info about whitelists. Can you point to any docs on this?

Some other info I found that may be if interest to others: "sort object properties and JSON.stringify" - tfzx.net/article/499097.html

Thanks so much for your post.

Collapse
 
sidvishnoi profile image
Sid Vishnoi • • Edited

From tc39.es/ecma262/#sec-json.stringify :

  1. 4.b.ii: If Type(replacer) is [Array]:
  2. 4.b.ii.g: If item is not undefined and item is not currently an element of PropertyList, then Append item to the end of PropertyList.

and later tc39.es/ecma262/#sec-serializejson... :

  1. 5.a: Let K be state.[[PropertyList]].
  2. 8: For each element P of K, do:
  3. 8.v: Append member to partial.
Thread Thread
 
getclibu profile image
Neville Franks •

Thanks for that. Pity it is missing from the MDN Doc's. For some reason the links didn't take me to the relevant sections.

Thread Thread
 
sidvishnoi profile image
Sid Vishnoi •

Updated links. DEV included trailing : in links, so they broke.

Thread Thread
 
getclibu profile image
Neville Franks •

Thanks, the links now work.

I didn't pick up on the ", but with limitation of maximum object depth 1" issue and I need to handle objects with depth > 1.

After some more searching I found this article which is a collection of code snippets. tfzx.net/article/499097.html

The code that worked for me is:

    var allKeys = [];
    JSON.stringify( json, function( key, value ){ allKeys.push( key ); return value; } )
    allKeys.sort();
Enter fullscreen mode Exit fullscreen mode

which is from: stackoverflow.com/a/53593328/91300

Collapse
 
martinratinaud profile image
Martin Ratinaud •

Brilliant! thanks