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