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))