Home > front end >  Spread inside JSON reviver function
Spread inside JSON reviver function

Time:06-21

I Would like to be able to spread out the value of an entry inside a JSON.parse reviver function while also drop the original key. Returning a spreaded value doesn't seem to do that trick.

here is an example:

const json = {a: 'foo', b: {c: 1, d: '2'}}
const stringify = JSON.stringify(json)

const parsed = JSON.parse(stringify, function(k, v) {
  if(k === 'b') {
    return {...v}
  } else {
    return v
  }
})

document.getElementById("app").innerHTML = `<pre>${JSON.stringify(parsed, null, 2)}</pre>`;
<div id="app"></div>

In the above the desired output should be

{
  "a": "foo",
  "c": 1,
  "d": "2"
}

CodePudding user response:

While I wouldn't recommend it as it's not very intuitive, you can use Object.assign(this, v) to merge with the this value in your replacer. This merges object at the b property into the object that the b property appears in, temporarily giving you:

{a: 'foo', b: {c: 1, d: '2'}, c: 1, d: '2'}

and then b is removed as we return undfined for that path, giving:

{a: 'foo', c: 1, d: '2'}

const json = {a: 'foo', b: {c: 1, d: '2'}};
const stringify = JSON.stringify(json)

const parsed = JSON.parse(stringify, function(k, v) {
  if(k === 'b') {
    Object.assign(this, v);
  } else {
    return v;
  }
});

document.getElementById("app").innerHTML = `<pre>${JSON.stringify(parsed, null, 2)}</pre>`;
<div id="app"></div>

CodePudding user response:

JSON.parse reviver only transform the value that is at key "b" and set it on that key. I would picture it similar to a map. Your solution should be outside the reviver function. Here is a sample of how your code could look like:

let { b, ...parsed } = JSON.parse(stringify);
if (b) {
  parsed = { ...parsed, ...b };
}

CodePudding user response:

@Geo Mircean answer is correct, but your comment add new information to the question.

If you have a complex structure, I don't think there is an easier option. The first one that comes to mind is to iterate the object and see if you need to spread each field. The logic to tell if you need to spread is up to you, but it will be something like:

let parsed = {...jsonObject};
for(let key in jsonObject)
{
  if (typeof jsonObject[key] === 'object') // if you want to spread
  {
    delete parsed[key]; // delete the actual key
    Object.assign(parsed, jsonObject[key]); // add fields to object
  }
}

Notice that the parsed variable will have our result. At first it get the whole object, then we iterate over the result, delete the field and spread the field value itself.

The Object.assign came from this StackOverflow question and does not work in IE9 (but I personally don't care about that).

  • Related