0

I have a weird JSON object. I am not sure how to iterate over it to get the values.

I can read a particular value but at a loss what to do next.

 var sku_object = {
   "SkuDevices": {
      "cb_skus": [
         {
            "XCZU9EG-1E": [
               {
                  "x_speed_alias": [
                     {
                        "$": 1
                     }
                  ],
                  "x_speed": [
                     {
                        "$": 1
                     }
                  ],
                  "device_speed": [
                     {
                        "$": "1REL"
                     }
                  ],
                  "hardware_product": [
                     {
                        "$": "XCZU9EG"
                     }
                  ],
                  "device_grade": [
                     {
                        "$": "E"
                     }
                  ],
                  "status": [
                     {
                        "$": "Active"
                     }
                  ]
               }
            ],
            "XCZU9EG-2I-4522": [
               {
                  "x_speed": [
                     {
                        "$": 2
                     },
                     {
                        "$": 2
                     }
                  ],
                  "x_speed_alias": [
                     {
                        "$": 2
                     }
                  ],
                  "spec_class": [
                     {
                        "$": "SCD"
                     }
                  ],
                  "device_speed": [
                     {
                        "$": "2REL"
                     }
                  ],
                  "x_spec_suffix": [
                     {
                        "$": 4522
                     }
                  ],
                  "spec_name": [
                     {
                        "$": "SCD4522"
                     }
                  ],
                  "hardware_product": [
                     {
                        "$": "XCZU9EG"
                     }
                  ],
                  "x_silicon_stage": [
                     {
                        "$": "PROD"
                     }
                  ],
                  "device_grade": [
                     {
                        "$": "I"
                     }
                  ],
                  "status": [
                     {
                        "$": "Active"
                     }
                  ]
               }
            ]
         }
      ],
      "device": [
         {
            "$": "ZU9EG"
         }
      ]
   }
}

alert (sku_object.SkuDevices["cb_skus"][0]["XCZU9EG-1E"][0]["device_speed"][0]["$"])

If you see the last line I can read a particular value.

Now under cb_skus -> XCZU9EG-1E and XCZU9EG-2I-4522 are different and it can be anything.

Again under XCZU9EG-2I-4522 the number of attributes differ.

I can only think so far:

 for (var i = 0, len = sku_object.XxpubSkuDeviceCollection.cb_skus.length; i < len; ++i) {
     var ss= sku_object.XxpubSkuDeviceCollection.cb_skus[i];
     alert (ss["XCZU9EG-1E"][0]["device_speed"][0]["$"])
 }

This doesnt really iterate over. Also how to get the keys like "device_speed"?

I should have added, the reason I am trying to iterate over it is to build a JSON object with the weird $ symbols. Something like this:

{
    "device" : "zu9eg",
    "cb_skus" : {
            "XCZU9EG-1E" : {"hardware_product" : "XCZU9EG",
                            "device_speed" : "1REL",
                            "x_speed" : "1",
                            "device_grade" : "E",
                            "status" : "active"
            },
            "XCZU9EG-2I-4522" : {"hardware_product" : "XCZU9EG",
                                 "device_speed" : "2REL",
                                 "x_speed" : "2",
                                 "x_speed_alias" : "2",
                                 "device_grade" : "I",
           }
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
user2351802
  • 90
  • 1
  • 1
  • 7
  • I should have added, the reason I am trying to iterate over it is to build a JSON object with the weird $ symbols. Something like this: – user2351802 Sep 02 '18 at 14:28
  • { "device" : "zu9eg", "cb_skus" : { "XCZU9EG-1E" : {"hardware_product" : "XCZU9EG", "device_speed" : "1REL", "x_speed" : "1", "status" : "active" }, "XCZU9EG-2I-4522" : {"hardware_product" : "XCZU9EG", "device_speed" : "2REL", "x_speed" : "2", "x_speed_alias" : "2", "device_grade" : "I", } } } – user2351802 Sep 02 '18 at 14:29
  • can you edit your post and add this informations please – JSmith Sep 02 '18 at 14:33
  • 1
    Start with https://stackoverflow.com/questions/8312459/iterate-through-object-properties. – Jim Janney Sep 02 '18 at 14:55
  • When asking a question please refer to the guidelines on the [How to Ask a Good Question](http://stackoverflow.com/help/how-to-ask) page. I don't see any evidence of [research](http://idownvotedbecau.se/noresearch/) here. – D.B. Sep 02 '18 at 15:02
  • @JSmith: Fixed the post. – user2351802 Sep 02 '18 at 15:19
  • @JimJanney - Thanks, I will look and try that out. – user2351802 Sep 02 '18 at 15:19
  • JSON is always a `String`, never an `Object`. – connexo Sep 02 '18 at 18:12

2 Answers2

1

Due to the strange array/object nesting nature of the given data, you need to map the arrays and fish the properties out of the sea of irregular deep swimming final keys.

Then form new objects with nested properties for easy, just two level deep, properties.

function final(a) {
    return '$' in a[0]
        ? a[0].$
        : Object.assign(
            ...a.map(o =>
                Object.assign(...Object.entries(o).map(([k, v]) => ({ [k]: final(v) })))
            )
        );
}

var sku_object = { SkuDevices: { cb_skus: [{ "XCZU9EG-1E": [{ x_speed_alias: [{ $: 1 }], x_speed: [{ $: 1 }], device_speed: [{ $: "1REL" }], hardware_product: [{ $: "XCZU9EG" }], device_grade: [{ $: "E" }], status: [{ $: "Active" }] }], "XCZU9EG-2I-4522": [{ x_speed: [{ $: 2 }, { $: 2 }], x_speed_alias: [{ $: 2 }], spec_class: [{ $: "SCD" }], device_speed: [{ $: "2REL" }], x_spec_suffix: [{ $: 4522 }], spec_name: [{ $: "SCD4522" }], hardware_product: [{ $: "XCZU9EG" }], x_silicon_stage: [{ $: "PROD" }], device_grade: [{ $: "I" }], status: [{ $: "Active" }] }] }], device: [{ $: "ZU9EG" }] } },
    result = final([sku_object.SkuDevices]);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Apologies for the delay in responding back. This solution also works as expected. I am just trying to understand how? Thanks – user2351802 Sep 04 '18 at 14:31
1

If JSON.parse is used to get the object, the values can be modified using the reviver parameter :

var j = '{"SkuDevices":{"cb_skus":[{"XCZU9EG-1E":[{"x_speed_alias":[{"$":1}],"x_speed":[{"$":1}],"device_speed":[{"$":"1REL"}],"hardware_product":[{"$":"XCZU9EG"}],"device_grade":[{"$":"E"}],"status":[{"$":"Active"}]}],"XCZU9EG-2I-4522":[{"x_speed":[{"$":2},{"$":2}],"x_speed_alias":[{"$":2}],"spec_class":[{"$":"SCD"}],"device_speed":[{"$":"2REL"}],"x_spec_suffix":[{"$":4522}],"spec_name":[{"$":"SCD4522"}],"hardware_product":[{"$":"XCZU9EG"}],"x_silicon_stage":[{"$":"PROD"}],"device_grade":[{"$":"I"}],"status":[{"$":"Active"}]}]}],"device":[{"$":"ZU9EG"}]}}'

var o = JSON.parse(j, (k, v) => v.map ? v[0] : v.$ || v)

console.log( o )

JSON.parse calls the reviver function for each parsed property and value pair, and the returned result is the value to be assigned to that property. The above sample re-written to be a bit more readable :

var json = '{"SkuDevices":{"cb_skus":[{"XCZU9EG-1E":[{"x_speed_alias":[{"$":1}],"x_speed":[{"$":1}],"device_speed":[{"$":"1REL"}],"hardware_product":[{"$":"XCZU9EG"}],"device_grade":[{"$":"E"}],"status":[{"$":"Active"}]}],"XCZU9EG-2I-4522":[{"x_speed":[{"$":2},{"$":2}],"x_speed_alias":[{"$":2}],"spec_class":[{"$":"SCD"}],"device_speed":[{"$":"2REL"}],"x_spec_suffix":[{"$":4522}],"spec_name":[{"$":"SCD4522"}],"hardware_product":[{"$":"XCZU9EG"}],"x_silicon_stage":[{"$":"PROD"}],"device_grade":[{"$":"I"}],"status":[{"$":"Active"}]}]}],"device":[{"$":"ZU9EG"}]}}';

var obj = JSON.parse(json, 
  function(key, value) {                               // for each parsed value, 
    if ( Array.isArray(value) ) { return value[0]; }   // if the value is array, return the first item. For example, [1, 2] becomes 1
    else if ( value.hasOwnProperty('$') ) { return value['$']; }    // if the value has a property "$", return it's value. For example, { "$": 1, "a": 2 } becomes 1
    else return value;                                 // otherwise, return the value unchanged for the rest of the values
  }
);

console.log( obj );
Slai
  • 22,144
  • 5
  • 45
  • 53
  • Apologies for the delay in responding back. That is magic. Can you please explain how this "(k, v) => v.map ? v[0] : v.$ || v" works? Thanks – user2351802 Sep 04 '18 at 14:30
  • Brilliant. Thanks a lot for the explanation. Not sure why this line " else if ( '$' in value ) { return value['$']; }" if showing error when testing in online tester https://www.webtoolkitonline.com/javascript-tester.html – user2351802 Sep 05 '18 at 17:45
  • true, I should have tested. `in` doesn't work for value types – Slai Sep 05 '18 at 17:55