Modern JavaScript: Customizing JSON Serialization
Welcome to the Customizing JSON Serialization lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
JSON.stringifytakes a JavaScript object or value as its argument, and turns it into JSON. We can customize its output by passing a second argument,replacer. For example, if we pass an array of strings as the replacer, then only keys names in the array will be included in the resulting object.>
JSON.parse(JSON.stringify({age: 36, city: 'Paris', name: 'Amir'},['name', 'city']));Result:
The replacer can also be a callback function taking two arguments,
keyandvalue. During stringification, our replacer is called with the key and value for each object, array, string, etc. We can replace any value by simply returning the new value that should take its place.In the next code example, we see this in action by logging the replacer's arguments at each step. Pay extra attention to the first logged line, where the overall object is passed to us with a key of
"". (Execute Program will show the console output, so you don't need to open your browser's built-in development console.)>
JSON.stringify({age: 36, name: 'Amir', cat: {name: 'Ms. Fluff'}},(key, value) => {console.log(`Key: ${JSON.stringify(key)}, value: ${JSON.stringify(value)}`);return value;});console outputThe first replacer call gets the entire object. The key is
""because we're not inside of an object yet. Then we see separate calls for the age, name, and cat keys. Finally,stringifydescends into the cat object, so we get a final call for itsnamekey. We didn't replace any data in this example, but we could've replaced the data in any of these steps, from the entire object down to a single deeply nested property.At each step, our replacer function can do three things:
- Return the
valueargument unmodified, which won't change the stringified object. - Return some other value, which will replace the original value in the stringified JSON.
- Return
undefined, which will remove the key from the stringified JSON.
- Return the
>
JSON.parse(JSON.stringify({name: 'Amir', catName: 'Ms. Fluff'},(key, value) => {if (typeof value === 'string') {return 'New ' + value;} else {return value;}}));Result:
>
JSON.parse(JSON.stringify({catName: 'Ms. Fluff', city: 'Paris', name: 'Amir'},(key, value) => {if (key === 'catName') {return undefined;} else {return value;}}));Result:
{city: 'Paris', name: 'Amir'}There's even more detail to the replacer function, but we won't cover its other functionality here. If you need to write a
JSON.stringifyreplacer, you should definitely have the documentation open anyway! The important thing to know is that this function exists, and that the replacer gets a chance to modify every part of the object as it's stringified. That should help you decide when it's appropriate to use.Finally,
JSON.parsehas a similar feature calledreviver. As the JSON is decoded, the reviver can replace any value with a new value.>
JSON.parse('{"name": "Amir"}');Result:
{name: 'Amir'}>
JSON.parse('{"name": "Amir", "age": 36}',(key, value) => {if (key === 'age' && value === 36) {return 'thirty-six';} else {return value;}});Result:
{name: 'Amir', age: 'thirty-six'}>
/* Note that the "reviver" function here replaces all property values in* the object! */JSON.parse('{"name": "Amir", "age": 36}',(key, value) => {if (key === '') {return value;} else {return 'nevermind';}});Result:
{name: 'nevermind', age: 'nevermind'}Reviver and replacer functions give us fine-grained control around stringifying and parsing data with JSON. This can be helpful when decoding third-party data whose format you don't control, or when formatting your own data to be shared as JSON. However, always consider whether the data transformation should be done separately, rather than in a replacer or reviver function. Often, transforming the data separately makes code easier to read.