0

I am trying to index through a JSON list in JavaScript but I'm having quite a lot of trouble getting it to work.

I have tried indexing through the values of each JSON item but it's not outputting what I want. I think I can get it to work but that would be with an extra unnecessary for loop level. Here is my JSON: https://pastebin.com/iYmaA4c5. If you think it would be better to reformat the JSON then that might help too.

function output_json(data) {
    var i, j, k;
    for (i=0; i<Object.keys(data).length; i++) {
        group_=Object.values(data)[i];
        for (j=0; j<Object.keys(group_).length; j++) {
            person=Object.values(group_)[j];
            person_id=Object.keys(person)[0];
            console.log(person_id);
            for (k=0; k<Object.keys(person).length; k++) {
                person_info=Object.values(person)[k][0];
                console.log(person_info);
            }
        }
    }
}

I want it to print out the id, and then the name, registration 1, registration 2, week and half_term for each id. At the moment it prints like this:

HA09_000

{name: "Wyatt Feldt", registration_1: "R", registration_2: "R", week: 0, half_term: 1}

But I want it to print like this for every single one:

HA09_000

Wyatt Feldt

R

R

0

1

Here is some Pseudo Code for what I would like to achieve:

FOR GROUP IN DATA:
    FOR PERSON IN GROUP:
        PRINT(PERSON.ID)
        FOR INFO IN PERSON:
            PRINT(INFO)

Thanks.

EDIT: This is the function I am using to retrieve the data:

$.getJSON("http://localhost:8000/data.json", function(data) {
    output_json(data);
});
Community
  • 1
  • 1
J P
  • 541
  • 1
  • 10
  • 20
  • If you need `Object.keys()` then it's not [JSON](http://json.org) but an object -> [What is the difference between JSON and Object Literal Notation?](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation) – Andreas Jan 19 '19 at 15:37
  • @Andreas Okay thanks, but how does that help me solve it? – J P Jan 19 '19 at 15:40
  • Don't you want to learn something that can make your life easier in the future, or that will straighten out a wrong understanding (because strings and objects are completely different)? – Andreas Jan 19 '19 at 16:12
  • @Andreas Yes of course, but it would be nice to learn it in a way that helps me better understand how to get a solution to my problem. – J P Jan 19 '19 at 16:15
  • Are you missing a closing bracket } on your for loop/function? – Sarah Jan 19 '19 at 16:22
  • @Sarah Yes, I pasted it wrong. Thanks! – J P Jan 19 '19 at 16:23
  • @J P No probs. I added an answer for your problem :) I found some useful information here: https://stackoverflow.com/questions/2958841/how-to-loop-through-key-value-object-in-javascript – Sarah Jan 19 '19 at 16:35

3 Answers3

2

Two useful ideas: (1) objects: if this is going to be a real system someday, and the data from the service represents groups of people, then the code ought to say that too. As an example, I've included a simple Person object who knows how to build itself from a flat representation and knows how to render itself on the console. (2) key ordering is not determined in JS object. To get values from specifically ordered keys, one must specify the ordering. The person print() method does this with an array.

See it here, running on a subset of the data...

$.getJSON("http://localhost:8000/data.json", function(data) {
    print_items(data);
});

class Person {
    constructor(data) {
        this.id = Object.keys(data)[0];
        this.state = data[this.id][0];
    }
    print() {
        console.log(this.id);
        let displayKeys = ['name', 'registration_1', 'registration_2', 'week', 'half_term'];
        displayKeys.forEach(key => console.log(this.state[key]));
    }
    asTableRow() {
        let displayKeys = ['name', 'registration_1', 'registration_2', 'week', 'half_term'];
        let tds = displayKeys.map(key => `<td>${this.state[key]}</td>`);
        return `<tr>${tds}</tr>`;
    }
}

function print_items(data) {
    Object.keys(data).forEach(groupKey => {
        let group = data[groupKey];
        Object.keys(group).forEach(personKey => {
            let person = new Person(group[personKey]);
            person.print();
        });
    });
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • Thanks. That works and makes a lot of sense. I just made a small edit to make it work with my localhost JSON file and I also made it a function. – J P Jan 19 '19 at 16:38
  • I am having some trouble though. I'm not used to this formatting and I can't get it to work with what I'm actually trying to do. What I really needed it to do was to insert a row into a table for each person, and each row contains 6 cells (groupKey, name, registration_1, registration_2, week, half_term). I just don't understand your code enough to get it to work for that. The way I did it previously was like this: https://pastebin.com/B3gbUinm (I added an expected result). Sorry to ask for more help but I just don't know how to make your code do that. – J P Jan 19 '19 at 16:59
  • This is a nice illustration why objects are good. I added a method whereby the Person object can render itself as a table row. I think you'll see from that how to get N rows from N people, and it ought to be straight forward to wrap that with a table tag. (Note, a static method on People might be a good place for that. Note also that the `displayKeys` might become a static method of its own. It is useful for two instance methods, and will be useful for a "headerRow()` method. I'll leave these as an exercise, because I have to be offline for about 12 hours, but can supply help later) – danh Jan 19 '19 at 17:13
0

You can clean up the internal loop by looking at each key and passing the value only. Also I suggest pulling the Object.keys(person).length out of your for loop because it will process what the keys are on every loop. If you put them into a variable and reference that it avoids reassessing the keys.

    var groups = Object.keys(testData);
    for(var i = 0; i<groups.length; i++){
        var group = testData[groups[i]];
        for(var j = 0; j<group.length; j++){
            var personEntry = group[j];
            var person_id = Object.keys(personEntry)[0];
            console.log(person_id);
            var personEntries = personEntry[person_id];
            for(var k = 0; k<personEntries.length; k++){
                var personValues = Object.values(personEntries[k]);
                for(var l = 0; l<personValues.length; l++){
                    console.log(personValues[l]);
                }
            }
        }
    }
GenericUser
  • 3,003
  • 1
  • 11
  • 17
  • Unfortunately it seems like it's not working. It's just outputting "HA09_000" then "0: {name: "Wyatt Feldt", registration_1: "R", registration_2: "R", week: 0, half_term: 1}" for each person. – J P Jan 19 '19 at 15:57
  • I see you edited your post, but now it prints "HA09_000" "H" "A" "0" "9". – J P Jan 19 '19 at 16:23
  • I had to rework it because the previous structure wasn't easy to reason with. Try this out instead. – GenericUser Jan 19 '19 at 16:28
  • Thanks but this is the way of doing it I referenced in my question (requires an extra for loop). I'm sure there is way of doing it like I described in my Pseudo Code (i.e. 3 for loops). – J P Jan 19 '19 at 17:05
0

Loop through the properties of the object using a for/in loop.

I have added the for/in loop to your code (using the person_info object) and tested it and it is printing what you desire. Hope this helps.

function output_json(data) {
    var i, j, k;
    for (i=0; i<Object.keys(data).length; i++) {
        group_=Object.values(data)[i];
        for (j=0; j<Object.keys(group_).length; j++) {
            person=Object.values(group_)[j];
            person_id=Object.keys(person)[0];   
            console.log(person_id);
            for (k=0; k<Object.keys(person).length; k++) {
                person_info=Object.values(person)[k][0];
                //loop through the properties of the person_info object
                //using a for/in loop
                for (var key in person_info) {
                   console.log(person_info[key]); 
                }              
            }
        }
    }
}
Sarah
  • 1,943
  • 2
  • 24
  • 39