skip to Main Content

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

2

Answers


  1. You need to handle the empty key passed to the replacer function.

    According to the documentation,

    The replacer function is called for the initial object being stringified as well, in which case the key is an empty string (""). It is then called for each property on the object or array being stringified. Array indices will be provided in its string form as key. The current property value will be replaced with the replacer’s return value for stringification.

    So that when you return an undefined value for the first entry, the stringified result is undefined.

    const o = {foo:1,bar:2,baz:3};
    
    console.log(
      `// {"foo":1}`, 
      JSON.stringify(o, (k,v) => k.startsWith('f') || k == "" ? v : undefined)
    ); 
    console.log(
      `// {"foo":1}`, 
      JSON.stringify(o, (k,v) => !k.startsWith('f') && k != "" ? undefined: v)
    );
        
    console.log(
      `// {"bar":2,"baz":3}`,
      JSON.stringify(o, (k,v) => !k.startsWith('f') ? v : undefined)
    );
    Login or Signup to reply.
  2. 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);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search