1

I am trying to update a nested JSON which is given as an input, e.g.:

{
    "doc": {
        "a1": {
            "b1": 1,
            "b2": [
                "one",
                "two"
            ]
        },
        "a2": "xyz"
    }
}

The JSON structure is not known.

Field to update is an input string eg: "doc.a2" or "doc.a1.b1" or "doc.a1.b2"

In addition to the path, the old value and a new value is also given as input. If the value in the path matches the old value, I want to update it with new value.


I tried with eval() and seems possible like if path is "doc.a1.b1", then eval(doc['a1']['b1']='new value');

But using eval may lead to security issues. Is there a better way to achieve this?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
AJS
  • 13
  • 2

3 Answers3

2

Don't reinvent the wheel - lodash's set can do this for you:

_.set(objToUpdate, 'doc.a1.b1', 'new_value');
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • In case you want to still do it on your own for some reason, you can split the string on '.', continually use and use reduce on the array returned to go to the nested space, but this answer is better – Aditya Rastogi Apr 02 '22 at 19:24
0

try this

var input1 = "doc.a2";
val1 = "val1";

updateVal(obj, input1, val1);
console.log("val1", obj);

function updateVal(obj, input, val) {
  let props = input.split(".");
  let currObj = obj;
  let index = 0;
  for (index = 0; index < props.length - 1; index++) {
    currObj = currObj[props[index]];
  };
  currObj[props[index]] = val;
};
Serge
  • 40,935
  • 4
  • 18
  • 45
0

Assuming you don't want to rely on a third party library, here is a 5-line proposal (it may need refinement to tackle corner cases such as invalid given path, depending on how you want to handle those cases, e.g. error, or create the path).

// given: ///////////////////////////////////

const obj = {
    "doc": {
        "a1": {
            "b1": 1,
            "b2": [
                "one",
                "two"
            ]
        },
        "a2": "xyz"
    }
}
const str = "doc.a1.b2"
const newValue = ["three"]

// do: ///////////////////////////////////////

const keys = str.split(".")
let ptr = obj
while(keys.length>1)
    ptr = ptr[keys.shift()]
ptr[keys.shift()] = newValue

// result:  ///////////////////////////////////

console.log(obj)
Vincent
  • 453
  • 3
  • 6