Search code examples
javascriptnested-loops

Parsing a nested object does not traverse the whole list with javascript


I'm trying to parse a nested object of the format:

const obj = {
  "and": [
      {
        "!=": [
          {
            "var": "name"
          },
          "name1"
        ]
      },
      {
        "in": [
          {
            "var": "hobbies"
          },
          "jogging, video games"
        ]
      }
    ]
};

I created a function to parse it:

const isOperatorCode(code) => {
  const allowedOperatorCodes = ['in', '<=', '!=', '=='];
  return allowedOperatorCodes.includes(code);
}

const parseObject = (arg, result={}) => {
  if (arg === undefined || arg === null) return arg;

  if (arg.constructor === Object && Object.keys(arg).length) {
    for (const key in arg) {
      const value = arg[key];
      if (key === 'and' || key === 'or' || key === '!') {
        result.operator = key === '!' ? 'not' : key;
        result.operands = [];
        return parseObject(value, result);
      }
      if (isOperatorCode(key)) {
        const newItem = {
          operator: key,
          attribute: value[0].var,
          value: value[1]
        }

        result.operands.push(newItem);

      }
    }
  }

  if(Array.isArray(arg) && arg.length) {
    for (const k of arg) {
      return parseObject(k, result);
    }
  }
  return result;
  
}

I got this result when I executed the function:

{"operator":"and","operands":[{"operator":"!=","attribute":"name","value":"name1"}]}

it should be:

{"operator":"and","operands":[{"operator":"!=","attribute":"name","value":"name1"}, {"operator":"in","attribute":"hobbies","value":"sport, video games"}]}

I know that the array does not keep the trace of the elements to continue looping through the different items. Any idea or suggestions to keep the track of the array elements and loop on them all?


Solution

  • If you return only at the very-end, you will get your expected result.

    const obj = {
      "and": [{
        "!=": [{
          "var": "name"
        }, "name1"]
      }, {
        "in": [{
          "var": "hobbies"
        }, "jogging, video games"]
      }]
    };
    
    const isOperatorCode = (code) => {
      const allowedOperatorCodes = ['in', '<=', '!=', '=='];
      return allowedOperatorCodes.includes(code);
    }
    
    const parseObject = (arg, result = {}) => {
      if (arg === undefined || arg === null) return arg;
      if (arg.constructor === Object && Object.keys(arg).length) {
        for (const key in arg) {
          const value = arg[key];
          if (key === 'and' || key === 'or' || key === '!') {
            result.operator = key === '!' ? 'not' : key;
            result.operands = [];
            parseObject(value, result);
          }
          if (isOperatorCode(key)) {
            const newItem = {
              operator: key,
              attribute: value[0].var,
              value: value[1]
            }
            result.operands.push(newItem);
          }
        }
      }
      if (Array.isArray(arg) && arg.length) {
        for (const k of arg) {
          parseObject(k, result);
        }
      }
      return result;
    }
    
    console.log(parseObject(obj));
    .as-console-wrapper { top: 0; max-height: 100% !important; }