Skip to content
Advertisement

How to keep the parent id of the children when creating an object recursively?

I have an object similar to this one:

const obj = {
    operator: 'AND',
    attributes: [
        {
            attribute: 'attr1',
            value: '123'
        },
        {
            attribute: 'attr2',
            value: '234'
        },
        {
            operator: 'OR',
            attributes: [
                {
                    attribute: 'attr3',
                    value: 'xxx' 
                }
            ]
        }
    ]
}

And I want to construct a tree from it:

{
    "id": "9aabbb89-cdef-4012-b456-7178a79bf800",
    "type": "group",
    "path": [
      "9aabbb89-cdef-4012-b456-7178a79bf800"
    ],
    "children1": {
      "a89aaa88-0123-4456-b89a-b178a79c0aab": {
        "type": "rule",
        "id": "a89aaa88-0123-4456-b89a-b178a79c0aab",
        "properties": {
          "attribute": "attr1",
          "value": "123"
        },
        "path": [
          "9aabbb89-cdef-4012-b456-7178a79bf800",
          "a89aaa88-0123-4456-b89a-b178a79c0aab"
        ]
      },
      "a9babbb8-cdef-4012-b456-7178a79c35ab": {
        "type": "rule",
        "id": "a9babbb8-cdef-4012-b456-7178a79c35ab",
        "properties": {
          "attribute": "attr2",
          "value": "234"
        },
        "path": [
          "9aabbb89-cdef-4012-b456-7178a79bf800",
          "a9babbb8-cdef-4012-b456-7178a79c35ab"
        ]
      },
      "b9aaabb9-0123-4456-b89a-b178a79cc5c2": {
        "type": "group",
        "id": "b9aaabb9-0123-4456-b89a-b178a79cc5c2",
        "properties": {
          "conjunction": "OR"
        },
        "path": [
          "9aabbb89-cdef-4012-b456-7178a79bf800",
          "b9aaabb9-0123-4456-b89a-b178a79cc5c2"
        ],
        "children1": {
          "9baa88b9-cdef-4012-b456-7178a79cc5c3": {
            "type": "rule",
            "id": "9baa88b9-cdef-4012-b456-7178a79cc5c3",
            "properties": {
              "attribute": "attr3",
              "value": "xxx"
            },
            "path": [
              "9aabbb89-cdef-4012-b456-7178a79bf800",
              "b9aaabb9-0123-4456-b89a-b178a79cc5c2",
              "9baa88b9-cdef-4012-b456-7178a79cc5c3"
            ]
          }
        }
    }
}
}

I write this code to create the tree:

function buildTree(obj) {
    if (!obj || !Object.keys(obj).length) return {};
    
    if ( 'attribute' in obj) {
        const id = uuid4();
        return {[id]: {
            id,
            type: 'rule',
            properties: {
                attribute: obj.attribute,
                value: obj.value,
                
            },
        }
    }
}   

    if (obj.operator === 'AND' || obj.operator === 'OR') {
        return { id: uuid4(),
        type: 'group',
        properties: {
            conjunction: obj.operator
        },
        children1: obj.operands.map(buildTree),
    }

}
}

However, I’m stucked how to keep the track of the parent ids of a children and save them in a path attribute. How can I fix that?

Advertisement

Answer

You have a recursive function, so just pass the path down through the calls (starting with an empty array) and append to it as you go:

function buildTree(obj, path = []) {
  if (!obj || !Object.keys(obj).length) return {};
  const id = uuid4()
  const newPath = [...path, id];
  if ('attribute' in obj) {
    return {
      [id]: {
        id,
        type: 'rule',
        path: newPath,
        properties: {
          attribute: obj.attribute,
          value: obj.value,

        },
      }
    }
  }

  if (obj.operator === 'AND' || obj.operator === 'OR') {
    
    return {
      id: id,
      type: 'group',
      path: newPath,
      properties: {
        conjunction: obj.operator
      },
      children1: obj.attributes.map(x => buildTree(x, newPath)),
    }

  }
}


const obj = {
  operator: 'AND',
  attributes: [{
      attribute: 'attr1',
      value: '123'
    },
    {
      attribute: 'attr2',
      value: '234'
    },
    {
      operator: 'OR',
      attributes: [{
        attribute: 'attr3',
        value: 'xxx'
      }]
    }
  ]
}

function uuid4() {
  let array = new Uint8Array(16)
  crypto.getRandomValues(array)

  // Manipulate the 9th byte
  array[8] &= 0b00111111 // Clear the first two bits
  array[8] |= 0b10000000 // Set the first two bits to 10

  // Manipulate the 7th byte
  array[6] &= 0b00001111 // Clear the first four bits
  array[6] |= 0b01000000 // Set the first four bits to 0100

  const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  let idx = 0

  return pattern.replace(
    /XX/g,
    () => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
  )
}



console.log(buildTree(obj));
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement