javascriptstringify

JSON.stringify replacer not working as expected (keep properties where name starts with)


I want to keep all property names that start with a certain string and remove all others from an object.

Why is the following not working - keep property foo only - and why does the opposite work? (test it here):

const o = {
  foo: 1,
  bar: 2,
  baz: 3
};
console.log(JSON.stringify(o, (k, v) => k.startsWith('f') ? v : undefined)); // undefined -> why not {"foo":1} ?
console.log(JSON.stringify(o, (k, v) => !k.startsWith('f') ? undefined : v)); // undefined -> why not {"foo":1} ?
console.log(JSON.stringify(o, (k, v) => !k.startsWith('f') ? v : undefined)); // {"bar":2,"baz":3}

Object.keys(o).forEach(key => {
  console.log(key, key.startsWith('f'));
});
// foo,true
// bar,false
// baz,false


Solution

  • Reading the docs of JSON.stringify

    The replacer function is called for the initial object being stringified as well, in which case the key is an empty string ("").

    And in your first two calls of JSON stringify, you return undefined when the key does not start with f (which is obviously the case, when key == ""). And so if the replacer for the initial object returns undefined, of course the result the whole stringification is undefined

    let o = { foo: 3, bar: 4, baz: 5}
    let s = JSON.stringify(o, (key, value) => !key 
      ? value 
      : key.startsWith("f") ? value : undefined);
    console.log(s);