DEV Community

Cover image for The secret power of JSON stringify
GÃĄbor SoÃģs
GÃĄbor SoÃģs

Posted on Edited on Originally published at sonicoder.com

The secret power of JSON stringify

There are many functions in Javascript that do their job. We use them daily, but we don't know about their extra features. At one day, we look at its documentation and realize it has many more features then we have imagined. The same thing has happened with JSON.stringify and me. In this short tutorial, I'll show you what I've learned.

Basics

The JSON.stringify method takes a variable and transforms it into its JSON representation.

const firstItem = { 
  title: 'Transformers', 
  year: 2007 
};

JSON.stringify(firstItem);
// {'title':'Transformers','year':2007}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

The problem comes when there is an element that can not serialize to JSON.

const secondItem = { 
  title: 'Transformers', 
  year: 2007, 
  starring: new Map([[0, 'Shia LaBeouf'],[1, 'Megan Fox']]) 
};

JSON.stringify(secondItem);
// {'title':'Transformers','year':2007,'starring':{}}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

The second argument

JSON.stringify has a second argument, which is called the replacer argument.

You can pass an array of strings that act as a whitelist for properties of the object to be included.

JSON.stringify(secondItem, ['title']);
// {'title':'Transformers'}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

We can filter out values that we don't want to display. These values can be too large items (like an Error object) or something that doesn't have a readable JSON representation.

The replacer argument can also be a function. This function receives the actual key and value on which the JSON.stringify method is iterating. You can alter the representation of the value with the function's return value. If you don't return anything from this function or return undefined, that item will not be present in the result.

JSON.stringify(secondItem, (key, value) => {
  if (value instanceof Set) {
    return [...value.values()];
  }
  return value;
});
// {'title':'Transformers','year':2007,'starring':['Shia LaBeouf','Megan Fox']}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

By returning undefined in the function, we can remove those items from the result.

JSON.stringify(secondItem, (key, value) => {
  if (typeof value === 'string') {
    return undefined;
  }
  return value;
});
// {"year":2007,"starring":{}}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Third argument

The third argument controls the spacing in the final string. If the argument is a number, each level in the stringification will be indented with this number of space characters.

JSON.stringify(secondItem, null, 2);
//{
//  "title": "Transformers",
//  "year": 2007,
//  "starring": {}
//}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

If the third argument is a string, it will be used instead of the space character.

JSON.stringify(secondItem, null, 'ðŸĶ„');
//{
//ðŸĶ„"title": "Transformers",
//ðŸĶ„"year": 2007,
//ðŸĶ„"starring": {}
//}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

The toJSON method

If the object what we stringify has a property toJSON, it will customize the stringification process. Instead of serializing the object, you can return a new value from the method, and this value will be serialized instead of the original object.

const thirdItem = { 
  title: 'Transformers', 
  year: 2007, 
  starring: new Map([[0, 'Shia LaBeouf'],[1, 'Megan Fox']]),
  toJSON() {
    return { 
      name: `${this.title} (${this.year})`, 
      actors: [...this.starring.values()] 
    };
  }
};

console.log(JSON.stringify(thirdItem));
// {"name":"Transformers (2007)","actors":["Shia LaBeouf","Megan Fox"]}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Demo time

Here is a Codepen where I included the above examples, and you can fiddle with it.

Final thoughts

It can be rewarding sometimes to look at the documentation of those functions we use daily. They might surprise us, and we learn something.
Stay hungry for knowledge and read the documentation ðŸĶ„.

Top comments (36)

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
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');
}
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

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

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
neilcodes profile image
Neil •

This is kind of horrifying and I love it.

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
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.

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
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.
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” 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.

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” Thread
 
sidvishnoi profile image
Sid Vishnoi •

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

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” 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();
ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

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

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
martinratinaud profile image
Martin Ratinaud •

Brilliant! thanks

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

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

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
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?

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sidvishnoi profile image
Sid Vishnoi •

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

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
areljannc profile image
AJ Clemente •

Wow! I'm a big fan of writing applications with JavaScript and its wide-varieties of libraries. I also don't post at all, ever, on any social platforms.

But this post is the first time that made we want to login and comment something.

Thanks for this amazing post! It's amazing that these simple methods are overlooked by many developers. Learning about this just now is the reason why I love programming.

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

Comments like this keep me motivated to keep on writing 👍 Thanks

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
rose profile image
Rose •

Great post, I use JSON.stringify all the time and I never new about this ðŸ˜ģlove finding out about these nooks and crannies of JS.

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

Glad it showed something new 👍

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
kenbellows profile image
Ken Bellows •

I've been using JavaScript deeply for a long time and it's very rare that I learn something new about old parts of JavaScript, but you've taught me two new things! I knew about the replacer function, I knew about the indentation, I even knew about toJSON, but I had never heard of either the property whitelist array or the indentation string options before! Thanks for the knowledge! 👏👏👏

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

I have used the indentation for a long time, but that null value before it always bothered me 😀

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sambenskin profile image
Sam Benskin •

Excellent article, I've never looked into the other arguments and the toJSON functionality is especially brilliant. Thanks for sharing!

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

toJSON was also absolutely new for me also

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
nditanaka profile image
Tanaka •

Thanks for the great post! Is there a way to easily unstringify text with a JavaScript? A kind of opposite of the stringify function? eg. how to remove the quotation marks in a dictionary of key-value pairs like {"name":"Tim", "age": "22"}. In this case, removing them just from the age value?

I have a more detailed version of this question on Stack Overflow that's been a little daunting to work around:

stackoverflow.com/questions/653516...

Thanks for the great article again!

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
jdhinvicara profile image
John Harding •

I am especially excited to be able to prefix my stringified objects with a unicorn!! ðŸĶ„ðŸĶ„ðŸĶ„

Seriously though, great article - every time I typed that null I wondered what that second argument was for and never got around to looking...

Thanks.

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

Thanks, unicorn all the way!!! ðŸĶ„ðŸĶ„ðŸĶ„

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
suprsidr profile image
Wayne Patterson •

Another super power is deep copying objects dassur.ma/things/deep-copy/

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
mdsardar profile image
Mohammed Sardar •

Thanks for the detailed sharing. Nice reading. It turned me very hunger for Java Script knowledge.

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

Stay hungry 👍

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
briandesousa1 profile image
Brian De Sousa •

Well done! Didn't know about those other arguments. The toJSON method is an interesting capability too. Thanks!

ðŸ”ī Hot News: sonicoder/the secret power of json stringify b - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
sonicoder profile image
GÃĄbor SoÃģs •

Thanks, yes indeed a real game changer

Some comments may only be visible to logged-in visitors. Sign in to view all comments.