Hagbard
Hagbard

Reputation: 575

Returning a nested value from JSON using jQuery

I'm receiving JSON from the server which looks something like this.

{"genres": [{
        "genre": "RPG",
        "publishers": [{
            "publisher": "Square",
            "games": [{
                "game": "FFX",
                "rating": [
                    12, 15
                ]
            }]
        }, {
            "publisher": "Blizzard",
            "games": [{
                "game": "Starcraft",
                "rating": [
                    10, 12
                ]
            }, {
                "game": "Diablo",
                "rating": [
                    15
                ]
            }, ]
        }]
    }, {
        "genre": "Action",
        "publishers": [{
            "publisher": "EA",
            "games": [{
                "game": "COD",
                "rating": [
                    18, 20
                ]
            }, {
                "game": "Titanfall",
                "rating": [
                    18
                ]
            }]
        }]
    }
}

I'm trying to build a drop down menu using the publishers from this data, at the moment i can get the Drop downs to return the genre, but not the publisher.

I've been trying to use .each to take the publisher from each genre, so in the drop down i will end up with: Square Blizzard EA

My code so far is:

  function renderCombo(){
  var parseData= JSON.parse($myData);
 $(parseData.Genre).each(function (i) {
     $("#pubCombo").append($("<option/>", {
         val: this.publisher,
         html: this.publisher
     }));
     $('#pubCombo').selectpicker("refresh");
 });

};

$myData is the data retrieved from the server, it works fine for all my other drop downs, so i know it's my renderCombo function.

Any ideas how this can be achieved?

Upvotes: 1

Views: 71

Answers (3)

Wilmer
Wilmer

Reputation: 2511

Add another each too traverse the publishers:

function renderCombo() {
    var parseData = JSON.parse($myData);
    $(parseData.genres).each(function (i) {
        $(this.publishers).each(function (i) {
            appendOption(this);
        });
    });
    $('#pubCombo').selectpicker("refresh");//refresh when finished
};

Updated to not append duplicate options:

function appendOption(option) {

    if ( !appendOption.distinct[option.publisher] ) {//check cache

        $("#pubCombo").append($("<option/>", {
            val: option.publisher,
            html: option.publisher
        }));
        appendOption.distinct[option.publisher] = option.publisher;

    }
}

appendOption.distinct= {};//cache

UPDATE: Improved second function to use a pseudo cache.

Upvotes: 1

Terry
Terry

Reputation: 66218

You don't have to use JSON.parse — jQuery can read objects and arrays directly without parsing :) you should also check your object for syntax errors, just in case.

If you intend to simply collect a list of all publishers in your data, you can use the code below:

$.each($myData.genres, function () {
    $.each(this.publishers, function() {
        $("#pubCombo").append($("<option/>", {
            val: this.publisher,
            html: this.publisher
        }));
    });
});

See proof-of-concept fiddle here: http://jsfiddle.net/teddyrised/N6FAk/

Update: If you want to return a unique array of publishers, you can use take advantage of jQuery's .unique() method:

var parseData = $myData,
    pubList = [];

$(parseData.genres).each(function () {
    $(this.publishers).each(function() {
        pubList.push(this.publisher);
    });
});

var uniquePubList = pubList.filter(function(v,i,pubList) {
    return i == pubList.indexOf(v);
});

$.each(uniquePubList, function (i,v) {
    $("#pubCombo").append($("<option/>", {
        val: v,
        html: v
    }));
});

See fiddle here: http://jsfiddle.net/teddyrised/N6FAk/3/

Upvotes: 2

Daniel Beck
Daniel Beck

Reputation: 21505

(Edited this answer now that I see the question really is how to eliminate duplicates)

The problem (besides some typos in your source data, and "Genre" instead of "genre" in your function) is that you have more than one publisher per genre, so you won't be able to get them in a single pass.

var uniquePublishers = {};
$(parsedData.genres).each(function () {
    $(this.publishers).each(function () {
        uniquePublishers[this.publisher] = true;
    });
});
for (publisher in uniquePublishers) {
    $("#pubCombo").append($("<option/>", {
        val: publisher,
        html: publisher
    }));
};

Fiddle

Upvotes: 2

Related Questions