JSON replacer is recursive. This then means it uses the same array for all objects it comes across. In other words, it uses the same values to map BAD.g's value. Since, Bad.g's value does not have any keys matching the ones you provided, nothing will get mapped properly. This means we have to add "2" to your array. Now "2" also has an object with different keys. We have already accounted for "b", so now we just need to add "w" to your array.

When providing an array to the replacer, best to think of the array as a list of all the keys you want mapped.

DEMO: http://jsfiddle.net/dirtyd77/whv7x6xc/4/

console.log(JSON.stringify(BAD, ['a', 'b', 'c', 'd', 'e', 'g', '2', 'w']));

Hope this helps and let me know if you have any questions.


Here is also a snippet from the documentation,

If you return any other object, the object is recursively stringified into the JSON string, calling the replacer function on each property, unless the object is a function, in which case nothing is added to the JSON string.


In the case for dynamic keys, you can always create a function to push to an array and use that array for your whitelist. Here is an example:

DEMO: http://jsfiddle.net/dirtyd77/whv7x6xc/5/

var BAD = {
    "a": "2",
    "b": 1,
    "c": "Nexus",
    "d": "Alligator",
    "e": 5,
    "f": 1431807036,
    "g": {
        "2": {
            "w": 17,
            "b": 5
        }
    }
}

var whitelist = [];

iterate(BAD);

console.log(whitelist, JSON.stringify(BAD, whitelist));

function iterate(obj){
    for(var key in obj){
        // may have to do some checking to ignore any keys you don't care about
        whitelist.push(key);
        // if value is an object, will use this same function to push to whitelist array
        if(typeof obj[key] === 'object'){
            return iterate(obj[key]);
        }
    }
}

You can also just use your existing whitelist and just append keys on your g key (given that isn't dynamic):

DEMO: http://jsfiddle.net/dirtyd77/whv7x6xc/6/

var whitelist = ['a', 'b', 'c', 'd', 'e', 'g'];

iterate(BAD.g);

console.log(whitelist, JSON.stringify(BAD, whitelist));

function iterate(obj){
    for(var key in obj){
        whitelist.push(key);
        if(typeof obj[key] === 'object'){
            return iterate(obj[key]);
        }
    }
}
Answer from Dom on Stack Overflow
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › JSON › stringify
JSON.stringify() - JavaScript - MDN Web Docs
The JSON.stringify() static method converts a JavaScript value to a JSON string, optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified.
🌐
pawelgrzybek
pawelgrzybek.com › til-the-power-of-json-stringify-replacer-parameter
TIL — The power of JSON.stringify replacer parameter | pawelgrzybek.com
JSON.stringify() takes a second optional argument that can be a recursive replacer function or an array of white-listed keys to be stringified.
Top answer
1 of 3
17

JSON replacer is recursive. This then means it uses the same array for all objects it comes across. In other words, it uses the same values to map BAD.g's value. Since, Bad.g's value does not have any keys matching the ones you provided, nothing will get mapped properly. This means we have to add "2" to your array. Now "2" also has an object with different keys. We have already accounted for "b", so now we just need to add "w" to your array.

When providing an array to the replacer, best to think of the array as a list of all the keys you want mapped.

DEMO: http://jsfiddle.net/dirtyd77/whv7x6xc/4/

console.log(JSON.stringify(BAD, ['a', 'b', 'c', 'd', 'e', 'g', '2', 'w']));

Hope this helps and let me know if you have any questions.


Here is also a snippet from the documentation,

If you return any other object, the object is recursively stringified into the JSON string, calling the replacer function on each property, unless the object is a function, in which case nothing is added to the JSON string.


In the case for dynamic keys, you can always create a function to push to an array and use that array for your whitelist. Here is an example:

DEMO: http://jsfiddle.net/dirtyd77/whv7x6xc/5/

var BAD = {
    "a": "2",
    "b": 1,
    "c": "Nexus",
    "d": "Alligator",
    "e": 5,
    "f": 1431807036,
    "g": {
        "2": {
            "w": 17,
            "b": 5
        }
    }
}

var whitelist = [];

iterate(BAD);

console.log(whitelist, JSON.stringify(BAD, whitelist));

function iterate(obj){
    for(var key in obj){
        // may have to do some checking to ignore any keys you don't care about
        whitelist.push(key);
        // if value is an object, will use this same function to push to whitelist array
        if(typeof obj[key] === 'object'){
            return iterate(obj[key]);
        }
    }
}

You can also just use your existing whitelist and just append keys on your g key (given that isn't dynamic):

DEMO: http://jsfiddle.net/dirtyd77/whv7x6xc/6/

var whitelist = ['a', 'b', 'c', 'd', 'e', 'g'];

iterate(BAD.g);

console.log(whitelist, JSON.stringify(BAD, whitelist));

function iterate(obj){
    for(var key in obj){
        whitelist.push(key);
        if(typeof obj[key] === 'object'){
            return iterate(obj[key]);
        }
    }
}
2 of 3
6

The replacer argument is deep, in that it affects the stringification of all properties, even if they're not on the first level. If you add "2" to the array, you'll see that the object is stringified, minus "w", because "w" is not allowlisted by replacer.

JSON.stringify(BAD, ['a', 'b', 'c', 'd', 'e', 'g', '2'])

Consider why you are using replacer. If you are using it to blocklist, instead of allowlist, you might be better served by passing in a function as opposed to an array.

JSON.stringify(BAD, function replacer(key, value) {
  var blocklist = ['b', 'g']
  return blocklist.indexOf(key) === -1 ? value : undefined
})
🌐
Dillion's Blog
dillionmegida.com › p › second-argument-in-json-stringify
The second argument in JSON.stringify() - Dillion's Blog
February 10, 2022 - If any value of the object is another object, the replacer method is recursively called on that object. And if any value of the object is a function, a symbol, or undefined, it will be ignored.
🌐
GitHub
gist.github.com › davidfurlong › 463a83a33b70a3b6618e97ec9679e490
JSON.stringify replacer function for having object keys sorted in output (supports deeply nested objects) · GitHub
JSON.stringify({c: new Number(1), a: { d: 0, c: 1, e: {a: 0, 1: 4}}}, replacer,2); '{\n' + ' "a": {\n' + ' "c": 1,\n' + ' "d": 0,\n' + ' "e": {\n' + ' "1": 4,\n' + ' "a": 0\n' + ' }\n' + ' },\n' + ' "c": {}\n' + <<<<===== OOPS! '}' const replacer = (key, value) => value instanceof Object && !(value instanceof Array) && !(value instanceof Function) && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof Boolean) && !(value instanceof Number) && !(value instanceof String) ?
🌐
Bennadel
bennadel.com › blog › 3278-using-json-stringify-replacer-function-to-recursively-serialize-and-sanitize-log-data.htm
Using JSON.stringify() Replacer Function To Recursively Serialize And Sanitize Log Data
April 21, 2020 - Ben Nadel demonstrates how the JSON.stringify() "replacer" function can be used to recursively serialize and sanitize log data. This is incredibly helpful for nested errors and log items that may contain Personally Identifiable Information (PII).
🌐
W3Schools
w3schools.com › jsref › jsref_stringify.asp
JavaScript JSON stringify() Method
JSON.stringify(obj, replacer, space) Using the replacer function: /*replace the value of "city" to upper case:*/ var obj = { "name":"John", "age":"39", "city":"New York"}; var text = JSON.stringify(obj, function (key, value) { if (key == "city") { return value.toUpperCase(); } else { return value; } }); Try it Yourself » ·
Find elsewhere
🌐
Medium
medium.com › @mujaffarhssn › are-you-familiar-with-the-hidden-powers-of-json-stringify-function-59e230accd99
Are You Familiar with the Hidden Powers of JSON.stringify() Function? | by TechInsights | Medium
November 4, 2023 - Here's the basic syntax: ... space: An optional parameter that specifies the indentation of nested structures in the resulting string. The replacer function is a powerful tool that allows us to customize the serialization process.
🌐
Esdiscuss
esdiscuss.org › topic › string-prototype-replace-problems-with-json-stringify-and-serialization-of-objects
String.prototype.replace() problems with JSON.stringify() and serialization of Objects
Example: var func = function() ... suggested optional flag An example implementation I made for showing the usage I would prefer: String.prototype.replace = function(key, value, ......
🌐
Nocommandline
nocommandline.com › blog › json-stringify-replacer-parameter-buffer-and-uint8array
JSON.stringify(), Replacer Parameter, Buffer and Uint8Array
January 29, 2023 - // This example was taken from ... {"week":45,"month":7} When it's a function: If you wish to "transform" the members of the JSON object while they're being converted to a string, you provide a function to do this as the second parameter (a replacer function)....
🌐
Dyn-web
dyn-web.com › tutorials › php-js › json › filter.php
Using a Replacer or Filter with JSON.stringify
February 3, 2015 - JSON.stringify has an optional second argument: a replacer or filter that can be a function or an array. If it is an array, it specifies by name which entries to include in the stringify result. If it is a function, it can be used to eliminate entries or change their values.
🌐
MDN
mdn2.netlify.app › en-us › docs › web › javascript › reference › global_objects › json › stringify
JSON.stringify() - JavaScript | MDN
March 27, 2022 - The JSON.stringify() method converts a JavaScript object or value to a JSON string, optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified.
🌐
RestfulAPI
restfulapi.net › home › json › json stringify()
JSON stringify() - REST API Tutorial
November 3, 2023 - JSON.stringify() can optionally use a replacer function to replace values using custom logic.
🌐
TutorialsPoint
tutorialspoint.com › javascript › javascript_json_stringify_method.htm
JavaScript - JSON.stringify() Method
In the example below, we use the JSON.stringify() method to convert a JavaScript value to a JSON string. We define a replacer function named modifyAge(), which increases the age by 5 for each record.
🌐
Joe Attardi
joeattardi.dev › customizing-jsonparse-and-jsonstringify
Customizing `JSON.parse` and `JSON.stringify` - Joe Attardi
February 15, 2025 - It is called first with the object itself, then is called again for each key/value pair. By the time it is called with the key/value pairs, the stringification of these properties has already been done.
🌐
ZetCode
zetcode.com › javascript › json-stringify
JavaScript JSON.stringify - Converting Objects to JSON
let json = JSON.stringify(value ... replacer is either a function that alters the behavior of the stringification process or an array which servers as a filter for the properties of the value object to be included in the JSON string....
🌐
Reality Ripple
udn.realityripple.com › docs › Web › JavaScript › Reference › Global_Objects › JSON › stringify
JSON.stringify() - JavaScript - UDN Web Docs: MDN Backup
The JSON.stringify() method converts a JavaScript object or value to a JSON string, optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified.
🌐
Edgecompute
js-compute-reference-docs.edgecompute.app › json.stringify()
JSON.stringify() | @fastly/js-compute
The JSON.stringify() method converts a JavaScript value to a JSON string, optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified.
🌐
Reddit
reddit.com › r/learnjavascript › json.stringify replacer
r/learnjavascript on Reddit: JSON.stringify replacer
July 15, 2020 -

Hello. I got a little confuse with FIRST argument that return JSON.stringify function replacer.So if I go:

let obj = { 
    a: 5,
    b: 10 
}

JSON.stringify(obj, (key, value) => { 
    if (key !== 'a') {
        return value;
    }
})

It'll fine

"{"b":10}"

But if I change function like this:

JSON.stringify(obj, (key, value) => {
    if (key === 'a') {
        return value;
    }
})

It returns undefined. Why? I think the point is that replacer function in first call get kinda anonymous object where key is <empty string> and value is {a: 5, b: 10}. And this anonymous object is very important for parsing to JSON string. And that's why second version, where passing only key === 'a', doesn't let this anonymous object return. Am I right?