Home > OS >  Parsing nested stringified json objects
Parsing nested stringified json objects

Time:10-01

I have some legacy code that returns nested stringified json as such:

"{ "value1": "name", "value2": "lastName", "value3": "{ \"subValue1\": \"\", \"subValue2\": null }" }"

and I am trying to write a parser function that would go into those nested objects, and parse them as well, however, I get a strange side effect where the parser does its job, but also adds extra values. Using example above it basically does this:

{
  0: "N",
  1: "O",
  value1: "name",
  value2: "NO",
  value3: {
    subValue1: "",
    subValue2: null,
  }
}

and I can't seem to debug it :/

Here is the parser in question:

const addValuesToObject = ({ object, keysArray, value }) => {
    for (let i = 0; i < keysArray.length; i  ) {
       const lastKey = i === keysArray.length - 1;
       object = object[keysArray[i]] = object[keysArray[i]] || (lastKey ? value : {});
    }
    
    return object;
 };

 const isStringifiedObject = (value) => typeof value === "string" && value[0] === "{" && value[value.length - 1] === "}";

 const nestedJsonParser = (stringifiedObject) => {
        
    if (!stringifiedObject) return {};

    let newObject = {};

    const parser = (value, objectPath = []) => {
      const isStringified = isStringifiedObject(value);

      // if it's a stringified object, parse and add values;
      if (isStringified) {
        const newParsedObject = JSON.parse(value);
        const keys = Object.keys(newParsedObject);

        keys.forEach((key) => {
          parser(newParsedObject[key], [...objectPath, key]);
        });
      } else {
        const newEntry = addValuesToObject({ value, keysArray: objectPath, object: newObject });
        newObject = { ...newObject, ...newEntry };
      }
    };

    parser(stringifiedObject);

    return newObject;
  };

if anyone can help me to avoid the whole adding of "0": "Y" thing, it would be greatly appreciated.

Edit: I'm fine with isStringifiedObject being a little wonky as it is, I don't expect to get usable strings that start/end with {}

CodePudding user response:

You can use JSON.parse with a "reviver" that recursively tries to parse every decoded string as json (and returns the argument as is if that fails):

function parseNested(str) {
    try {
        return JSON.parse(str, (_, val) => {
            if (typeof val === 'string')
                return parseNested(val)
            return val
        })
    } catch (exc) {
        return str
    }
}

// demo

obj = {
    'abc': 'def',
    'foo': 'bar',
    'nest1': JSON.stringify({deep1: 123}),
    'nest2': JSON.stringify({deep2: JSON.stringify({deep3: ['something', 'else']})}),
}

weird = JSON.stringify(obj)
console.log(weird)
console.log(parseNested(weird))

  • Related