Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

159
Views
Detecting JSON Subschema in JavaScript

My JSON could have "n" layers of subschema - How can I detect if a key has a subschema under it to prevent if from looping incorrectly as it's doing today? As you can see in my code below I am starting to consider moving the subschemas to arrays, but this feels like a workaround, not the correct approach. Lastly, is it possible to avoid multiple FOR loops to better handle the "n" layers of subschema.

jsfiddle

HTML

<table></table>

Javascript

var data = {
  "THREE LEVEL": {
    "PRODUCTION": {
      "One": "http://one.com",
      "Two": "http://two.com"
    },
    "LATEST": {
      "alpha": "http://alpha.com",
      "omega": "http://omega.com"
    },
    "STAGE": {
      "Apha": "http://alpha.com",
      "Bravo": "http://bravo.com", 
      "Charley": "http://charley.com"
    }
  },
  "TWO LEVEL": {
    "PRODUCTION": "http://aaa.com",
    "LATEST": "http://bbb.com",
    "STAGE": "http://ccc.com"
  }
}

var table = document.querySelector('table');
var rows = '';

for (var lev_1 in data) {
  rows += '<tr><td>' + lev_1 + '</td><td></td></tr>'
  //if(Array.isArray(data[lev_1])){
    for (var lev_2 in data[lev_1]) {
      rows += '<tr><td><a href="' + data[lev_1][lev_2] + '">' + lev_2 + '</td><td></td></tr>'
      //if(Array.isArray(data[lev_1][lev_2])) {
        for (var lev_3 in data[lev_1][lev_2]) {
          rows += '<tr><td><a href="' + data[lev_1][lev_2][lev_3] + '">' + lev_3 + '</td><td></td></tr>'
        }
      //}
    }  
  //}
}
table.innerHTML = rows;

Current Output

THREE LEVEL 
PRODUCTION  
One 
Two 
LATEST  
alpha   
omega   
STAGE   
Apha    
Bravo   
Charley 
TWO LEVEL   
PRODUCTION  
0   
1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
LATEST  
0   
1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
STAGE   
0   
1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Use typeof() to determine what kind of element you're dealing with.

  • If its an object then use Object.keys() to get an array of all of the keys within the object. Then iterate through the keys, testing each with typeof()...

  • If it's an array, then iterate through each element of the array testing each with typeof()

  • Rinse and repeat.

The following example should give you a better idea of how to proceed.

var data = {
  "THREE LEVEL": {
    "PRODUCTION": {
      "One": "http://one.com",
      "Two": "http://two.com"
    },
    "LATEST": {
      "alpha": "http://alpha.com",
      "omega": "http://omega.com"
    },
    "STAGE": {
      "Apha": "http://alpha.com",
      "Bravo": "http://bravo.com",
      "Charley": "http://charley.com"
    }
  },
  "TWO LEVEL": {
    "PRODUCTION": "http://aaa.com",
    "LATEST": "http://bbb.com",
    "STAGE": "http://ccc.com"
  }
}

var table = document.querySelector('table');
var rows = '';

var iterateObject = function(dataObject) {
  var keys = Object.keys(dataObject);
  keys.forEach(function(key) {
    var textArray = [];
    var element = dataObject[key];
    switch (typeof(element)) {
      case 'object':
        textArray.push(key)
        dumpRow(textArray);
        iterateObject(element);
        break;
      case 'array':
        textArray.push(key)
        dumpRow(textArray);
        iterateArray(element);
        break;
      default:
        dumpElement(dataObject, key);
        break;
    }
  });
};

var iterateArray = function(dataArray) {
  dataArray.forEach(function(element) {
    switch (typeof(element)) {
      case 'object':
        iterateObject(element);
        break;
      case 'array':
        iterateArray(element);
        break;
      default:
        var textArray = [];
        textArray.push(element)
        dumpRow(textArray);
        break;
    }
  });
};

var dumpElement = function(obj, key) {
  var textArray = [];
  textArray.push(key);
  textArray.push(obj[key]);
  dumpRow(textArray);
};

var dumpRow = function(textArray) {
  var dumpString = '<tr>';
  textArray.forEach(function(text) {
    dumpString += dumpCell(text);
  });
  dumpString += '</tr>';
  rows += dumpString;
};

var dumpCell = function(dumpText) {
  var dumpString = '<td>';
  dumpString += dumpText;
  dumpString += '</td>';
  return dumpString;
};

switch (typeof(data)) {
  case 'object':
    iterateObject(data);
    break;
  case 'array':
    iterateArray(data);
    break;
  default:
    var textArray = [];
    textArray.push(data)
    dumpRow(textArray);
    break;
}

table.innerHTML = rows;
<html>

<body>
</body>
<table>
</table>

</html>

about 4 years ago · Juan Pablo Isaza Report

0

You should probably make some kind of TableMaker:

//<![CDATA[
/* js/external.js */
let doc, htm, bod, nav, M, I, mobile, S, Q, TableMaker; // for use on other loads
addEventListener('load', () => {
  doc = document;
  htm = doc.documentElement;
  bod = doc.body;
  nav = navigator;
  M = tag => doc.createElement(tag);
  I = id => doc.getElementById(id);
  mobile = /Mobi/i.test(nav.userAgent);
  S = (selector, within) => {
    let w = within || doc;
    return w.querySelector(selector);
  }
  Q = (selector, within) => {
    let w = within || doc;
    return w.querySelectorAll(selector);
  }
  TableMaker = function(object) {
    this.table = M('table');
    this.thead = M('thead');
    this.tbody = M('tbody');
    this.tfoot = M('tfoot');
    this.trMake = () => {
      return M('tr');
    }
    this.thMake = textContent => {
      const th = M('th');
      th.textContent = textContent;
      return th;
    }
    this.tdMake = textContent => {
      const td = M('td');
      td.textContent = textContent;
      return td;
    }
    if (object !== undefined) {
      let tr, o, n, td;
      for (let k in object) {
        tr = this.trMake();
        if (typeof k === 'string') {
          tr.appendChild(this.tdMake(k));
          this.tbody.appendChild(tr);
          o = object[k];
          if (typeof o === 'string') {
            tr.appendChild(this.tdMake(o));
          } else {
            n = new TableMaker(object[k]);
            td = this.tdMake();
            td.appendChild(n.table);
            tr.append(td);
          }
        }
      }
    }
    this.table.appendChild(this.thead);
    this.table.appendChild(this.tbody);
    this.table.appendChild(this.tfoot);
  }
  // magic below can be put on a separate page - except // end load line
  var data = {
    "THREE LEVEL": {
      "PRODUCTION": {
        "One": "http://one.com",
        "Two": "http://two.com"
      },
      "LATEST": {
        "alpha": "http://alpha.com",
        "omega": "http://omega.com"
      },
      "STAGE": {
        "Apha": "http://alpha.com",
        "Bravo": "http://bravo.com",
        "Charley": "http://charley.com"
      }
    },
    "TWO LEVEL": {
      "PRODUCTION": "http://aaa.com",
      "LATEST": "http://bbb.com",
      "STAGE": "http://ccc.com"
    }
  }
  const tM = new TableMaker(data);
  bod.appendChild(tM.table);
}); // end load
//]]>
table {
  border: 1px solid #000;
}

td {
  border: 1px solid #090;
}

You'll notice I've included a small library, as well. Note the recursive nature of TableMaker.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!