Search code examples
javascriptfor-in-loop

For/In Loop through JavaScript Data


Before being redirected to a similar question: I checked related questions. I understand the thing. I just can't seem to apply it to my specific code correctly.

I'm trying to display JSON data using Javascript. It worked perfectly fine. Then I added one level, and now I'm completely lost.

Initially, I had my overall data (1), my 3 entries (2), and the 3 properties of each entry (3).

I grabbed the data like this:

var objDisplay = document.getElementById('myDiv');

for (key1 in this.jsonObj){ 

    for (var x = 0; x < this.jsonObj[key1].length; x++){ 
        var objEntry = document.createElement('div'); 

        for (key2 in this.jsonObj[key1][x]){

            var sPropertyData = this.jsonObj[key1][x][key2]; 
            var objProperty = document.createElement('div');
            objProperty.appendChild(document.createTextNode(sPropertyData));
            objEntry.appendChild(objProperty);

        }

        objDisplay.appendChild(objEntry);
    }

}

Now I want to triple the entries and split them into sections, so I'll have my overall data (1), my 3 sections (2), the 3 entries of each section (3), and the 3 properties of each entry (4). I also want to display each section in a separate div.

I know the answer is probably ridiculously easy to figure out with the foundation I have, but I just can't visualize it right now, and my attempts led to...weird results. Help?

edit: The new data object, where each letter is a section

{
    "ABC": [

        {"A": 
            [
                { "1" : "A1-1", "2" : "A1-2", "3" : "A1-3"},
                { "1" : "A2-1", "2" : "A2-2", "3" : "A2-3" },
                { "1" : "A3-1", "2" : "A3-2", "3" : "A3-3" }
            ]
        },

        {"B": 
            [
                { "1" : "B1-1", "2" : "B1-2", "3" : "B1-3"},
                { "1" : "B2-1", "2" : "B2-2", "3" : "B2-3" },
                { "1" : "B3-1", "2" : "B3-2", "3" : "B3-3" }
            ]
        },

        {"C": 
            [
                { "1" : "C1-1", "2" : "C1-2", "3" : "C1-3"},
                { "1" : "C2-1", "2" : "C2-2", "3" : "C2-3" },
                { "1" : "C3-1", "2" : "C3-2", "3" : "C3-3" }
            ]
        }
    ]
}

edit 2: Expected output (don't mind the class names, they're for reference only)

<div id="myDiv">
  <div class="section">
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
  </div>
  <div class="section">
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
  </div>
  <div class="section">
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
    <div class="entry">
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
        <div class="property">stringified json data</div>
    </div>
  </div>
</div>

The only data I need textually is the value of the lowest level, but I need to be able to use the higher levels for styling purposes (see created divs in initial code).


Solution

  • Don't use for in loops for looping over objects, instead use array forEach with object.keys. Otherwise, you forgot to iterate over the inner-most object. However, a recursive function could make this work regardless of how deep you nest it, assuming you keep the same structure of Object > Array > Object > String

    var jsonObj = {
      "ABC": [
    
        {
          "A": [{
            "1": "A1-1",
            "2": "A1-2",
            "3": "A1-3"
          }, {
            "1": "A2-1",
            "2": "A2-2",
            "3": "A2-3"
          }, {
            "1": "A3-1",
            "2": "A3-2",
            "3": "A3-3"
          }]
        },
    
        {
          "B": [{
            "1": "B1-1",
            "2": "B1-2",
            "3": "B1-3"
          }, {
            "1": "B2-1",
            "2": "B2-2",
            "3": "B2-3"
          }, {
            "1": "B3-1",
            "2": "B3-2",
            "3": "B3-3"
          }]
        },
    
        {
          "C": [{
            "1": "C1-1",
            "2": "C1-2",
            "3": "C1-3"
          }, {
            "1": "C2-1",
            "2": "C2-2",
            "3": "C2-3"
          }, {
            "1": "C3-1",
            "2": "C3-2",
            "3": "C3-3"
          }]
        }
      ]
    };
    var objDisplay = document.getElementById('myDiv');
    
    function recurse(obj, level) {
      console.log(level);
      var div = document.createElement('div');
      switch (level) {
        case 1:
          div.className = 'section';
          break;
        case 2:
          div.className = 'entry';
          break;
        case 3:
          div.className = 'property';
          break;
      }
      Object.keys(obj).forEach(function(key) {
        if (typeof obj[key] === 'string') {
          var prop = document.createElement('div');
          prop.className = 'property';
          var tempObj = {};
          tempObj[key] = obj[key]
          prop.appendChild(document.createTextNode(JSON.stringify(tempObj)))
          div.appendChild(prop);
          return;
        }
        obj[key].forEach(function(obj) {
          div.appendChild(recurse(obj,level + 1));
        });
      });
      return div;
    }
    
    objDisplay.appendChild(recurse(jsonObj,0));
    .section {
      border: 1px solid green;
      margin: 5px;
      padding: 5px;
    }
    .entry {
      border: 1px solid blue;
      margin: 5px;
      padding: 5px;
    }
    .property {
      border: 1px solid yellow;
      margin: 5px;
      padding: 5px;
    }
    <div id="myDiv"></div>