简体   繁体   中英

How do i store keys while flattening?

I have a nested JSON object which is of the format

[{
  firstLevelKey1 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey2:[{
    dataType : 'Object'
  },{
    value : [{
      secondLevelKey1 :[{
        dataType : 'String'
      },{
        value : 'someString'
      },{
        someKey : 'someValue'
      }]
    },{
      secondLevelKey2 : [{
        dataType : 'Object'
      },{
        value : [{
          thirdLevelKey1:[{
            dataType : 'String'
          },{
            value : 'someString'
          },{
            someKey : 'someValue'
          }]
        },{
          thirdLevelKey2 : [{
            dataType : 'String'
          },{
            value : 'someString'
          },{
            someKey : 'someValue'
          }]
        },{
          thirdLevelKey3 : [{
            dataType : 'String'
          },{
            value : 'someString'
          },{
            someKey : 'someValue'
          }]
        }]
      },{
        someKey : 'someValue'
      }]
    },{
      secondLevelKey3 :[{
        dataType : 'String'
      },{
        value : 'someString'
      },{
        someKey : 'someValue'
      }]
    }]
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey3 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
}]

for easier understanding this is an array of objects, in each object, the value of key is again an array of 3 objects, of which first tells the dataType and there is value in the second object, and some other keys in third object.

If the dataType is Object then the second object which has the key property called value will have again array of objects repeating the procedure.

I am able to flatten and the flattened object is like

[{
  firstLevelKey1 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  secondLevelKey1 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  thirdLevelKey1 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  thirdLevelKey2 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  thirdLevelKey3 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  secondLevelKey3 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey3 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
}]

but now firstLevelKey2 property name and secondLevelKey2 name are lost

is there a way to store the names so that while mapping back i can know how to nest them back in the same format how i recieved it? like for example in this format


[{
  firstLevelKey1 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey2#secondLevelKey1 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey2#secondLevelKey2#thirdLevelKey1 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey2#secondLevelKey2#thirdLevelKey2 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey2#secondLevelKey2#thirdLevelKey3 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey2#secondLevelKey3 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
},{
  firstLevelKey3 : [{
    dataType : 'String'
  },{
    value : 'someString'
  },{
    someKey : 'someValue'
  }]
}]

any help would be very appreciated.Thanks!

You could use a recursive approach here, creating a flattenWithPath function that takes an array and path as arguments.

By passing the path for each call we can ensure we can retain the object hierarchy in the key names.

 const input = [{ firstLevelKey1: [{ dataType: 'String' },{ value: 'someString' },{ someKey: 'someValue' }] },{ firstLevelKey2:[{ dataType: 'Object' },{ value: [{ secondLevelKey1:[{ dataType: 'String' },{ value: 'someString' },{ someKey: 'someValue' }] },{ secondLevelKey2: [{ dataType: 'Object' },{ value: [{ thirdLevelKey1:[{ dataType: 'String' },{ value: 'someString' },{ someKey: 'someValue' }] },{ thirdLevelKey2: [{ dataType: 'String' },{ value: 'someString' },{ someKey: 'someValue' }] },{ thirdLevelKey3: [{ dataType: 'String' },{ value: 'someString' },{ someKey: 'someValue' }] }] },{ someKey: 'someValue' }] },{ secondLevelKey3:[{ dataType: 'String' },{ value: 'someString' },{ someKey: 'someValue' }] }] },{ someKey: 'someValue' }] },{ firstLevelKey3: [{ dataType: 'String' },{ value: 'someString' },{ someKey: 'someValue' }] }] function flattenWithPath(arr, path = []) { let result = []; for (let obj of arr) { const [key, value] = Object.entries(obj)[0]; if (Array.isArray(value[1].value)) { result.push(...flattenWithPath(value[1].value, [...path, key])); } else { result.push({ [[...path, key].join('#')]: value }); } } return result; } console.log(JSON.stringify(flattenWithPath(input), null, 2))
 .as-console-wrapper { max-height: 100%;important; }

Here's another take.

const input = [{ firstLevelKey1 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ firstLevelKey2:[{ dataType : 'Object' },{ value : [{ secondLevelKey1 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ secondLevelKey2 : [{ dataType : 'Object' },{ value : [{ thirdLevelKey1:[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey2 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ secondLevelKey3 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ firstLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] 

function flatObj(obj, path = []) {
    return Object.entries(obj).flatMap(([k, v]) =>
        v[0].dataType === 'Object' ?
            v[1].value.flatMap(obj => flatObj(obj, [...path, k])) :
            [{[[...path, k].join('#')]: v}]
    );
}

console.log(input.flatMap(obj => flatObj(obj)));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM