简体   繁体   中英

iterating through object

I'm having a really hard time trying to find a way to iterate through this object in the way that I'd like. I'm using only Javascript here.

First, here's the object

{
"dialog":
{
    "dialog_trunk_1":{
        "message": "This is just a JSON Test"
    },
    
    "dialog_trunk_2":{
        "message": "and a test of the second message"
    },

    "dialog_trunk_3":
    {
        "message": "This is a test of a bit longer text. Hopefully this will at the very least create 3 lines and trigger us to go on to another box. So we can test multi-box functionality, too."
    }
}
}

Right now, I'm just trying basic ways to get through to each dialog_trunk on this object. I ideally want to loop through the object and for each trunk, display it's message value.

I've tried using a for loop to generate the name/number of the dialog_trunk on the fly, but I can't access the object using a string for the object name so I'm not sure where to go from here.

You use a for..in loop for this. Be sure to check if the object owns the properties or all inherited properties are shown as well. An example is like this:

var obj = {a: 1, b: 2};
for (var key in obj) {
  if (obj.hasOwnProperty(key)) {
    var val = obj[key];
    console.log(val);
  }
}

Or if you need recursion to walk through all the properties:

var obj = {a: 1, b: 2, c: {a: 1, b: 2}};
function walk(obj) {
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      var val = obj[key];
      console.log(val);
      walk(val);
    }
  }
}
walk(obj);

My problem was actually a problem of bad planning with the JSON object rather than an actual logic issue. What I ended up doing was organize the object as follows, per a suggestion from user2736012.

{
"dialog":
{
    "trunks":[
    {
        "trunk_id" : "1",
        "message": "This is just a JSON Test"
    },
    {
        "trunk_id" : "2",
        "message": "This is a test of a bit longer text. Hopefully this will at the very least create 3 lines and trigger us to go on to another box. So we can test multi-box functionality, too."
    }
    ]
}
}

At that point, I was able to do a fairly simple for loop based on the total number of objects.

var totalMessages = Object.keys(messages.dialog.trunks).length;

    for ( var i = 0; i < totalMessages; i++)
    {
        console.log("ID: " + messages.dialog.trunks[i].trunk_id + " Message " + messages.dialog.trunks[i].message);
    }

My method for getting totalMessages is not supported in all browsers, though. For my project, it actually doesn't matter, but beware of that if you choose to use something similar to this.

Here is my recursive approach:

function visit(object) {
    if (isIterable(object)) {
        forEachIn(object, function (accessor, child) {
            visit(child);
        });
    }
    else {
        var value = object;
        console.log(value);
    }
}

function forEachIn(iterable, functionRef) {
    for (var accessor in iterable) {
        functionRef(accessor, iterable[accessor]);
    }
}

function isIterable(element) {
    return isArray(element) || isObject(element);
}

function isArray(element) {
    return element.constructor == Array;
}

function isObject(element) {
    return element.constructor == Object;
}

An improved version for recursive approach suggested by @schirrmacher to print key[value] for the entire object:

var jDepthLvl = 0;
function visit(object, objectAccessor=null) {
  jDepthLvl++;
  if (isIterable(object)) {
    if(objectAccessor === null) {
      console.log("%c ⇓ ⇓ printing object $OBJECT_OR_ARRAY$ -- START ⇓ ⇓", "background:yellow");
    } else
      console.log("%c"+spacesDepth(jDepthLvl)+objectAccessor+"%c:","color:purple;font-weight:bold", "color:black");
    forEachIn(object, function (accessor, child) {
      visit(child, accessor);
    });
  } else {
    var value = object;
    console.log("%c"
      + spacesDepth(jDepthLvl)
      + objectAccessor + "[%c" + value + "%c] "
      ,"color:blue","color:red","color:blue");
  }
  if(objectAccessor === null) {
    console.log("%c ⇑ ⇑ printing object $OBJECT_OR_ARRAY$ -- END ⇑ ⇑", "background:yellow");
  }
  jDepthLvl--;
}

function spacesDepth(jDepthLvl) {
  let jSpc="";
  for (let jIter=0; jIter<jDepthLvl-1; jIter++) {
    jSpc+="\u0020\u0020"
  }
  return jSpc;
}

function forEachIn(iterable, functionRef) {
  for (var accessor in iterable) {
    functionRef(accessor, iterable[accessor]);
  }
}

function isIterable(element) {
  return isArray(element) || isObject(element);
}

function isArray(element) {
  return element.constructor == Array;
}

function isObject(element) {
  return element.constructor == Object;
}


visit($OBJECT_OR_ARRAY$);

使用来自@eric 的 JSON 的控制台输出

 var res = { "dialog": { "dialog_trunk_1":{ "message": "This is just a JSON Test" }, "dialog_trunk_2":{ "message": "and a test of the second message" }, "dialog_trunk_3": { "message": "This is a test of a bit longer text. Hopefully this will at the very least create 3 lines and trigger us to go on to another box. So we can test multi-box functionality, too." } } } for (var key in res) { if (res.hasOwnProperty(key)) { var val = res[key]; for (var key in val) { if (val.hasOwnProperty(key)) { var dialog = val[key]; console.log(dialog.message); } } } }

The simpler approach is (just found on W3Schools):

let data = {.....}; // JSON Object
for(let d in data){
    console.log(d); // It gives you property name
    console.log(data[d]); // And this gives you its value
}

UPDATE

This approach works fine until you deal with the nested object so this approach will work.

const iterateJSON = (jsonObject, output = {}) => {
  for (let d in jsonObject) {
    if (typeof jsonObject[d] === "string") {
      output[d] = jsonObject[d];
    }
    if (typeof jsonObject[d] === "object") {
      output[d] = iterateJSON(jsonObject[d]);
    }
  }
  return output;
}

And use the method like this

let output = iterateJSON(your_json_object);

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