0

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!

1
  • With my solution it's a short one-line recursive function, please check Commented Dec 30, 2022 at 6:17

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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;
    }

4 Comments

Thank you for such an optimized solution!
Your welcome, this solution is likely the fastest
Yes, but currently still doesnt have the key-value pair for the primitives in the generated JSON output
Oops, I overlooked that. Now updated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.