I need to parse a JSON object recursively.
Here is a sample JSON:
const obj = {
tag: 'AA',
type: 'constructed',
value: 'ABCD1',
child: [
{
tag: 'BB',
type: 'constructed',
value: 'ABCD2',
child: [
{
tag: 'CC',
type: 'constructed',
value: 'ABCD3',
child: [
{
tag: 'DD',
type: 'primitive',
value: 'ABCD4',
child: []
},
{
tag: 'EE',
type: 'constructed',
value: 'ABCD5',
child: [
{
tag: 'FF',
type: 'primitive',
value: 'ABCD6',
child: []
},
{
tag: 'GG',
type: 'primitive',
value: 'ABCD7',
child: []
}
]
},
{
tag: 'HH',
type: 'primitive',
value: 'ABCD8',
child: []
}
]
}
]
},
{
tag: 'II',
type: 'primitive',
value: 'ABCD9',
child: []
}
]
}
And the output should be something like:
{
"AA": [
{
"BB": [
{
"CC": [
{
"DD": "ABCD4"
},
{
"EE": [
{
"FF": "ABCD6"
},
{
"GG": "ABCD7"
}
]
},
{
"HH": "ABCD8"
}
]
}
]
},
{
"II": "ABCD9"
}
]
}
Basically, those with type constructed
should have a nested object and those that are primitive
should directly have a key-value pair. The object could go very deep, and can have both constructed and primitive objects on the same level (as on my example).
Here is my current code:
let jsonOutput = {}
parseData(obj, jsonOutput)
function parseData(jsonToParse, jsonOutput) {
const type = jsonToParse.type
const tag = jsonToParse.tag
const value = jsonToParse.value
let prev = jsonOutput
if (type === 'constructed') {
prev[tag] = []
return parseData(jsonToParse.child[0], prev[tag])
} else if (type === 'primitive') {
prev[tag] = value
return parseData(jsonToParse.child, prev[tag])
}
}
Here is my fiddle: https://jsfiddle.net/kzaiwo/0v6a2tp8/16/
But I can't make it iterate through the whole object. Recursions are not really my strongest area, but I think this is the most optimal way to implement it.. What am I missing? Help please!
Thanks!
CodePudding user response:
Hope this may help you,
const obj = { tag: 'AA', type: 'constructed', value: 'ABCD1', child: [ { tag: 'BB', type: 'constructed', value: 'ABCD2', child: [ { tag: 'CC', type: 'constructed', value: 'ABCD3', child: [ { tag: 'DD', type: 'primitive', value: 'ABCD4', child: [] }, { tag: 'EE', type: 'constructed', value: 'ABCD5', child: [ { tag: 'FF', type: 'primitive', value: 'ABCD6', child: [] }, { tag: 'GG', type: 'primitive', value: 'ABCD7', child: [] } ] }, { tag: 'HH', type: 'primitive', value: 'ABCD8', child: [] } ] } ] }, { tag: 'II', type: 'primitive', value: 'ABCD9', child: [] } ] }
function parseData(obj) {
const result = {};
if (obj.type === 'primitive') {
result[obj.tag] = obj.value;
} else if (obj.type === 'constructed') {
result[obj.tag] = obj.child.map(parseData);
}
return result;
}
const parsedJson = parseData(obj);
console.log(parsedJson);
CodePudding user response:
You can use the following recursive reduceObj(obj)
function, short and sweet:
const obj = { tag: 'AA', type: 'constructed', value: 'ABCD1', child: [ { tag: 'BB', type: 'constructed', value: 'ABCD2', child: [ { tag: 'CC', type: 'constructed', value: 'ABCD3', child: [ { tag: 'DD', type: 'primitive', value: 'ABCD4', child: [] }, { tag: 'EE', type: 'constructed', value: 'ABCD5', child: [ { tag: 'FF', type: 'primitive', value: 'ABCD6', child: [] }, { tag: 'GG', type: 'primitive', value: 'ABCD7', child: [] } ] }, { tag: 'HH', type: 'primitive', value: 'ABCD8', child: [] } ] } ] }, { tag: 'II', type: 'primitive', value: 'ABCD9', child: [] } ] }
function reduceObj(obj) {
return { [obj.tag]: obj.type === 'primitive'
? obj.value
: obj.child.map(reduceObj) };
}
const result = reduceObj(obj);
console.log(result);
Function syntax prior to ES6:
function reduceObj(obj) {
let o = {};
o[obj.tag] = obj.child.map(function(childObj) {
return obj.type === 'primitive'
? obj.value
: reduceObj(childObj);
});
return o;
}