2

I'm trying to transform this JSON into array so that I can simply list them as key-value pairs in html. The JSON has nested properties which I want to retain but I want to stringify only those objects that contain "units" and "value". All others should be listed as children items. Please help figure what I'm doing wrong.

Here's the json input:

  {
  "clusterName": "ml6.engrlab.com-cluster",
  "statusProperties": {
    "loadProperties": {
      "loadDetail": {
        "restoreWriteLoad": {
          "value": 0,
          "units": "sec/sec"
        },
      },
      "totalLoad": {
        "value": 0.0825921967625618,
        "units": "sec/sec"
      }
    },
    "secure": {
      "value": false,
      "units": "bool"
    },
    "statusDetail": {
      "licenseKeyOption": [
        {
          "value": "conversion",
          "units": "enum"
        },
        {
          "value": "failover",
          "units": "enum"
        }
      ],
      "connectPort": 7999,
      "softwareVersion": {
        "value": 9000100,
        "units": "quantity"
      }
    },
    "rateProperties": {
      "rateDetail": {
        "largeReadRate": {
          "value": 0,
          "units": "MB/sec"
        }
      },
      "totalRate": {
        "value": 67.2446365356445,
        "units": "MB/sec"
      }
    },
    "online": {
      "value": true,
      "units": "bool"
    },
    "cacheProperties": {
      "cacheDetail": {
        "tripleCachePartitions": {
          "tripleCachePartition": [
            {
              "partitionSize": 768,
              "partitionBusy": 0,
              "partitionUsed": 0,
              "partitionFree": 100
            }
          ]
        }
      }
    }
  }
}

my code

function isNested(obj) {
if(!obj) return false;

let propArry = Object.keys(obj)
for(let i=0; i<propArry.length; i++){
  if(obj[propArry[0]].constructor.name === 'Object') return true
}
  return false;
} 


function getKeyValueAsChildren(obj) {
  let vals = [];
  for(let key in obj) {
    if(obj.hasOwnProperty(key)){
      vals.push({key:key, value: obj[key]})
    }
  }
  return vals
}

function valueAsString(obj) {
  if(typeof obj !== 'object') return obj;

  return `${obj['value']} ${obj['units']}`
}

function getChildren(key, obj) {
   if(Object.keys(obj).sort().toString() === "units,value"){
         return {key: key, value: valueAsString(obj)}            
     } else {
         return {key: key, children: getKeyValueAsChildren(obj) }            
   }
}

function getValues(properties, values = []) {
for(let key in properties) {
    if(properties.hasOwnProperty(key)) {
      let value =  properties[key]
      if(typeof value !== 'object') {
        values.push({key: key, value: value})  
      } else if(Array.isArray(value)){
        let children = []
        value.map(v => {
          children.push(getChildren(key, v))  
        })  
        values.push({key: `${key}List`, children: children})
      } 
      else if(value.constructor.name === 'Object' && isNested(value)){
        // I THINK THE MAIN PROBLEM IS HERE
        let keys = Object.keys(value)
        let children = [];
        keys.forEach(key => {
          children.push({key: key, children: getValues(value[key])})
        })
        values.push({key: key, children: children})
      } 
       else {
          values.push(getChildren(key, value))
      }
    }
}
return values
}

getValues(hostProperties)

this returns

    [
    {
        "key": "clusterName",
        "value": "ml6.engrlab.com-cluster"
    },
    {
        "key": "statusProperties",
        "children": [
            {
                "key": "loadProperties",
                "children": [
                    {
                        "key": "loadDetail",
                        "children": [
                            {
                                "key": "restoreWriteLoad",
                                "children": [
                                    {
                                        "key": "value",
                                        "value": 0
                                    },
                                    {
                                        "key": "units",
                                        "value": "sec/sec"
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "key": "totalLoad",
                        "value": "0.0825921967625618 sec/sec"
                    }
                ]
            },
            {
                "key": "secure",
                "children": [
                    {
                        "key": "value",
                        "value": false
                    },
                    {
                        "key": "units",
                        "value": "bool"
                    }
                ]
            },
            {
                "key": "statusDetail",
                "children": [
                    {
                        "key": "licenseKeyOptionList",
                        "children": [
                            {
                                "key": "licenseKeyOption",
                                "value": "conversion enum"
                            },
                            {
                                "key": "licenseKeyOption",
                                "value": "failover enum"
                            }
                        ]
                    },
                    {
                        "key": "connectPort",
                        "value": 7999
                    },
                ]
            },
            {
                "key": "rateProperties",
                "children": [
                    {
                        "key": "rateDetail",
                        "children": [
                            {
                                "key": "largeReadRate",
                                "children": [
                                    {
                                        "key": "value",
                                        "value": 0
                                    },
                                    {
                                        "key": "units",
                                        "value": "MB/sec"
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "key": "totalRate",
                        "value": "67.2446365356445 MB/sec"
                    }
                ]
            },
            {
                "key": "online",
                "children": [
                    {
                        "key": "value",
                        "value": true
                    },
                    {
                        "key": "units",
                        "value": "bool"
                    }
                ]
            },
            {
                "key": "cacheProperties",
                "children": [
                    {
                        "key": "cacheDetail",
                        "children": [
                            {
                                "key": "tripleCachePartitions",
                                "children": [
                                    {
                                        "key": "tripleCachePartitionList",
                                        "children": [
                                            {
                                                "key": "tripleCachePartition",
                                                "children": [
                                                    {
                                                        "key": "partitionSize",
                                                        "value": 768
                                                    },
                                                    {
                                                        "key": "partitionBusy",
                                                        "value": 0
                                                    },
                                                    {
                                                        "key": "partitionUsed",
                                                        "value": 0
                                                    },
                                                    {
                                                        "key": "partitionFree",
                                                        "value": 100
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

but I need this

[
{
    "key": "clusterName",
    "value": "ml6.engrlab.com-cluster"
},
{
    "key": "statusProperties",
    "children": [
        {
            "key": "loadProperties",
            "children": [
                {
                    "key": "loadDetail",
                    "children": [
                        {
                            "key": "restoreWriteLoad",
                            "value": "0 sec/sec"
                        }
                    ]
                },
                {
                    "key": "totalLoad",
                    "value": "0.0825921967625618 sec/sec"
                }
            ]
        },
        {
            "key": "secure",
            "value": "false bool"
        },
        {
            "key": "statusDetail",
            "children": [
                {
                    "key": "licenseKeyOptionList",
                    "children": [
                        {
                            "key": "licenseKeyOption",
                            "value": "conversion enum"
                        },
                        {
                            "key": "licenseKeyOption",
                            "value": "failover enum"
                        }
                    ]
                },
                {
                    "key": "connectPort",
                    "value": 7999
                }
            ]
        },
        {
            "key": "rateProperties",
            "children": [
                {
                    "key": "rateDetail",
                    "children": [
                        {
                            "key": "largeReadRate",
                            "value": "0 MB/sec"
                        }
                    ]
                },
                {
                    "key": "totalRate",
                    "value": "67.2446365356445 MB/sec"
                }
            ]
        },
        {
            "key": "online",
            "value": "true bool"
        },
        {
            "key": "cacheProperties",
            "children": [
                {
                    "key": "cacheDetail",
                    "children": [
                        {
                            "key": "tripleCachePartitions",
                            "children": [
                                {
                                    "key": "tripleCachePartitionList",
                                    "children": [
                                        {
                                            "key": "tripleCachePartition",
                                            "children": [
                                                {
                                                    "key": "partitionSize",
                                                    "value": 768
                                                },
                                                {
                                                    "key": "partitionBusy",
                                                    "value": 0
                                                },
                                                {
                                                    "key": "partitionUsed",
                                                    "value": 0
                                                },
                                                {
                                                    "key": "partitionFree",
                                                    "value": 100
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

]

3
  • Welcome to StackOverflow. Please read and follow the posting guidelines in the help documentation. Minimal, complete, verifiable example applies here. We cannot effectively help you until you post your MCVE code and accurately describe the problem. Cut down the input example to something that succinctly exhibits the problem. Commented Mar 29, 2017 at 22:47
  • Also, please explain why the many on-line solutions for JSON parsing don't satisfy your needs in this case. Commented Mar 29, 2017 at 22:48
  • Hi, this is indeed the most simplified form of my problem. The JSON is way bigger than what I've posted. I have cut down to small set that covers all cases I need to handle. The output format that I'm looking is very specific to my needs Commented Mar 29, 2017 at 22:55

1 Answer 1

1

You might have to run more tests, as what you require seems quite arbitrary, but I believe this function does what you are looking for. It works in a similar way to yours, by simply recursing the tree, and checking for object types, and if the special case is matched.

function toKeyValue(obj) {
  return Object.keys(obj).map(k => {    
    var value = obj[k]
    var key = k 
    var valueName = 'children'
    if(Array.isArray(value)){
      key = k + 'List'
      value = value.map(toKeyValue)
    }else if(value !== null && typeof value === 'object'){
      // check for special case
      if(Object.keys(value).sort().toString() === "units,value"){
        value = value.value + ' ' + value.units
        valueName = 'value'
      }else{
        value = toKeyValue(value)
      }      
    }else{
      valueName = 'value'
    }
    return {
      key: key,
      [valueName]: value
    }
  })
}

Fiddle here

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

3 Comments

Thanks Matt, it almost works except for array objects. Ex: licenseKeyOption list contains objects of "units" and "values" which are not transformed to string
The line in array condition should be map(toKeyValue). SO does not allow me to update. Anyway I'll accept this your answer. Thanks again!
Sorry, wrote it quickly. Have updated with your fix.

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.