简体   繁体   中英

How to convert this json data into an array of key,value pair in js?

I have a nested json data where each parent has a array or object as a child, I have tried a naive approach of iterating over the json data to get in key:value form but the code is not optimal in complexity as well as readability. Can someone suggest a way by which we can reduce the complexity of this one to get desired output?

The desired output is an array of objects where each object has a key and a value. The key name is the value of key from payload preceded with it's parent name as per dot notation. Also the main constraint we have is that we are not sure, which child element can further be further nested. Is there a way where we can avoid this nesting of so many loops to access child elements?

This is the json payload (data) consisting of nested objects and arrays:

[{
  "id": {
    "no": null,
    "uid": null,
    "dataBody": {
      "area": "Universe",
      "place": "LMN",
      "information1": [{
        "code": "abc",
        "group": "xyz",
        "data": [{
            "definition": {
              "type": "up",
              "features": {
                "featurekey": "ABC",
                "featureValues": null
              },
              "mandatory": true,
            },
            "cost": {
              "currency": "USD",
              "value": 1,
            }
          },
          {
            "definition": {
              "type": "down",
              "mandatory": true,
            },
            "cost": "100"
          },
          {
            "definition": {
              "type": "left",
              "value": null,
              "mandatory": true,
            },
            "cost": false
          }
        ],
      }],
      "hobby": {
        "indoor": false,
        "outdoor": true,
      },
      "petName": "Tiger",
    },
    "details": "detail",
    "phone": "contact"
  }
}]

Code:

const payload = data[0]
const dataBody = payload["id"]["dataBody"]
const answer =[]

// adds child of id which are not an object like no,uid,details,phone gets added in key:value pair
for(let keys in payload["id"]){
    if(keys != "dataBody"){
        answer.push({"ref":`${keys}`,"value":payload["id"][keys]})
    }
}

for(let keys in dataBody){
  if(keys!="information" && keys!="hobby"){
      answer.push({"ref":`dataBody.${keys}`,"value":dataBody[keys]})
  }
}

const information1 = dataBody["information1"]

const hobby = dataBody["hobby"]

for(let keys in hobby){
    answer.push({"ref":`hobby.${keys}`,"value":hobby[keys]})
}

const object ={}  // definition and cost

for(let keys=0; keys<information1.length;keys++){
  const infoValue = keys + 1
  const temp = []
  for(let infoParameters in information1[keys]){
      if(infoParameters != "data"){
        answer.push({"ref":`info${infoValue}.${infoParameters}`,"value":information1[keys][infoParameters]})
      } else {
          const data = information1[keys]["data"]
          for(let i=0;i<data.length;i++){
              temp.push(data[i])
          }

      }
  }
  object[keys]=temp
}

let counter = 0

for(const keys in object){
  const dfValues = object[keys]
  counter = counter + 1
  for(let i=0;i<dfValues.length;i++){
    const definition = dfValues[i]["definition"]
    const cost = dfValues[i]["cost"]
    for(const fdValues in definition){
        if(fdValues === "features"){
            for(let featureValues in definition[fdValues]){ // maybe bad logic, need to refin
                answer.push({"ref":`info${counter}.df${counter}.definition${i+1}.${fdValues}.${featureValues}`, "val": definition[fdValues][featureValues]})
            }
        } else {
          answer.push({"ref":`info${counter}.df${counter}.definition${i+1}.${fdValues}`, "val": definition[fdValues]})
        }
    }
    if(typeof(cost) === "object"){
      for(const fValues in cost){
          answer.push({"ref":`info${counter}.df${counter}.cost${i+1}.${fValues}`, "val": cost[fValues]})
      }
    } else{
        answer.push({"ref":`info${counter}.df${counter}.cost${i+1}`,"val":cost})
    }

  }
}
console.log(answer)

Output:

[
  { ref: 'no', value: null },
  { ref: 'uid', value: null },
  { ref: 'details', value: 'detail' },
  { ref: 'phone', value: 'contact' },
  { ref: 'dataBody.area', value: 'Universe' },
  { ref: 'dataBody.place', value: 'LMN' },
  { ref: 'dataBody.information1', value: [ [Object] ] },
  { ref: 'dataBody.petName', value: 'Tiger' },
  { ref: 'hobby.indoor', value: false },
  { ref: 'hobby.outdoor', value: true },
  { ref: 'info1.code', value: 'abc' },
  { ref: 'info1.group', value: 'xyz' },
  { ref: 'info1.df1.definition1.type', val: 'up' },
  { ref: 'info1.df1.definition1.features.featurekey', val: 'ABC' },  
  { ref: 'info1.df1.definition1.features.featureValues', val: null },
  { ref: 'info1.df1.definition1.mandatory', val: true },
  { ref: 'info1.df1.cost1.currency', val: 'USD' },
  { ref: 'info1.df1.cost1.value', val: 1 },
  { ref: 'info1.df1.definition2.type', val: 'down' },
  { ref: 'info1.df1.definition2.mandatory', val: true },
  { ref: 'info1.df1.cost2', val: '100' },
  { ref: 'info1.df1.definition3.type', val: 'left' },
  { ref: 'info1.df1.definition3.value', val: null },
  { ref: 'info1.df1.definition3.mandatory', val: true },
  { ref: 'info1.df1.cost3', val: false }
]

You can use recursive to list them

[
  {
    "name": "data.0.id.no",
    "value": null
  },
  {
    "name": "data.0.id.uid",
    "value": null
  },
  {
    "name": "data.0.id.dataBody.area",
    "value": "Universe"
  },
  {
    "name": "data.0.id.dataBody.place",
    "value": "LMN"
  },
  {
    "name": "data.0.id.dataBody.information1.0.code",
    "value": "abc"
  },
  {
    "name": "data.0.id.dataBody.information1.0.group",
    "value": "xyz"
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.0.definition.type",
    "value": "up"
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.0.definition.features.featurekey",
    "value": "ABC"
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.0.definition.features.featureValues",
    "value": null
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.0.definition.mandatory",
    "value": true
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.0.cost.currency",
    "value": "USD"
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.0.cost.value",
    "value": 1
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.1.definition.type",
    "value": "down"
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.1.definition.mandatory",
    "value": true
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.1.cost",
    "value": "100"
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.2.definition.type",
    "value": "left"
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.2.definition.value",
    "value": null
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.2.definition.mandatory",
    "value": true
  },
  {
    "name": "data.0.id.dataBody.information1.0.data.2.cost",
    "value": false
  },
  {
    "name": "data.0.id.dataBody.hobby.indoor",
    "value": false
  },
  {
    "name": "data.0.id.dataBody.hobby.outdoor",
    "value": true
  },
  {
    "name": "data.0.id.dataBody.petName",
    "value": "Tiger"
  },
  {
    "name": "data.0.id.details",
    "value": "detail"
  },
  {
    "name": "data.0.id.phone",
    "value": "contact"
  }
]

The function:

var output = Array();

function iterate(data, name, output)
{
    for(let key in data)
    {
        let value = data[key];

        if(value != null && (typeof(value) == "object" || typeof(value) == "array"))
        {
            iterate(value, name + "." + key, output);
        }
        else
        {
            output.push({name:name + "." + key, value:value});
        }
    }
}


iterate(data, "data", output);

console.log("Output", JSON.stringify(output, 0, 2));

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