A.G.Progm.Enthusiast
A.G.Progm.Enthusiast

Reputation: 1010

How to recursively process a JSON data and return the processed JSON from a function?

I have below JSON data with nested objects. I want to delete the 'id' from this structure and return the changed JSON from the function. I have tried to do it recursively below way but not able to return the changed JSON.

var jsonStr = 
{"_id":"7r0c0342e",
"user":"myuser",
"project":"abcd",
"info":{"DOMAIN":{"Department":{"profile":[{"workex":8,"name":"alex","id":82838},
{"workex":8,"name":"smith","id":84838} ]}}} };


processJSON(jsonStr);

function processJSON(jsondata) {
    for (var i in jsondata) {
        var row = jsondata[i];           
        if(typeof row == "object") {
            processJSON(row);              
        } else if(typeof row == 'number') {
            if(i == 'id') {
                delete jsondata[i];                    
            } else {                
                continue;
            }
        } else {
            continue;
        }              
      }   
}

console.log(jsonStr);

How can I return the rest of the JSON from the processJSON() and hold that in a variable ? Secondly, is this the correct way to do it recursively ?

Thanks.

Upvotes: 4

Views: 112

Answers (3)

vincent
vincent

Reputation: 2181

Here is a solution using object-scan that modifies the data in place...

// const objectScan = require('object-scan');

const jsonStr = { _id: '7r0c0342e', user: 'myuser', project: 'abcd', info: { DOMAIN: { Department: { profile: [{ workex: 8, name: 'alex', id: 82838 }, { workex: 8, name: 'smith', id: 84838 }] } } } };

const prune = (obj) => objectScan(['**.id'], {
  rtn: 'count',
  filterFn: ({ parent, property }) => {
    delete parent[property];
    return true;
  }
})(obj);

console.log(prune(jsonStr)); // returns amount of deletes
// => 2
console.log(jsonStr);
// => { _id: '7r0c0342e', user: 'myuser', project: 'abcd', info: { DOMAIN: { Department: { profile: [ { workex: 8, name: 'alex' }, { workex: 8, name: 'smith' } ] } } } }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

...and a different solution that clones the input and omits the ids in the clone process...

// const objectScan = require('object-scan');

const jsonStr = { _id: '7r0c0342e', user: 'myuser', project: 'abcd', info: { DOMAIN: { Department: { profile: [{ workex: 8, name: 'alex', id: 82838 }, { workex: 8, name: 'smith', id: 84838 }] } } } };

const clone = (obj) => objectScan(['**', '!**.id'], {
  breakFn: ({ isMatch, property, value, isLeaf, context }) => {
    if (!isMatch) {
      return;
    }
    const ref = context[context.length - 1];
    if (!(property in ref)) {
      if (isLeaf) {
        ref[property] = value;
      } else {
        ref[property] = Array.isArray(value) ? [] : {};
      }
    }
    context.push(ref[property]);
  },
  filterFn: ({ context }) => {
    context.pop();
  }
})(obj, [{}])[0];

const r = clone(jsonStr);
console.log(jsonStr);
// => { _id: '7r0c0342e', user: 'myuser', project: 'abcd', info: { DOMAIN: { Department: { profile: [ { workex: 8, name: 'alex', id: 82838 }, { workex: 8, name: 'smith', id: 84838 } ] } } } }
console.log(r);
// => { info: { DOMAIN: { Department: { profile: [ { name: 'alex', workex: 8 }, { name: 'smith', workex: 8 } ] } } }, project: 'abcd', user: 'myuser', _id: '7r0c0342e' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

Upvotes: 0

Amit Wagner
Amit Wagner

Reputation: 3264

var jsonStr =
    {
        "_id": "7r0c0342e",
        "user": "myuser",
        "project": "data_mining",
        "info": {
            "DOMAIN": {
                "Department": {
                    "profile": [{"workex": 8, "name": "alex", "id": 82838},
                        {"workex": 8, "name": "smith", "id": 84838}]
                }
            }
        }
    };
let modifedJson = JSON.parse(JSON.stringify(jsonStr));

parseJson = function (json) {
    for (let key in json) {
        if (key === 'id') {
            delete json[key];
        }
        else if (typeof json[key] === 'object') {
            parseJson(json[key])
        }

    }
}
parseJson(modifedJson)
console.log('modified',modifedJson)
console.log('original',jsonStr)

Upvotes: 1

TimoStaudinger
TimoStaudinger

Reputation: 42460

With your approach, you mutate the original object, so in a way, you don't have to return anything.

If you want to keep the original object and return a changed copy instead, you will first need to make a copy of the object, and run your algorithm on that. You can make a shallow copy of an object e.g. using Object.assign:

var jsonStr = {"_id":"7r0c0342e", "user":"myuser", "project":"data_mining", "info":{"DOMAIN":{"Department":{"profile":[{"workex":8,"name":"alex","id":82838}, {"workex":8,"name":"smith","id":84838} ]}}} };

console.log(processJSON(jsonStr));

function processJSON(jsondata) {
  var output = Object.assign({}, jsondata)

  for (var i in output) {
    var row = output[i];
    if (typeof row == "object") {
      output[i] = processJSON(row);
    } else if (typeof row == 'number') {
      if (i == 'id') {
        delete output[i];
      } else {
        continue;
      }
    } else {
      continue;
    }
  }

  return output;
}

Upvotes: 4

Related Questions