78

I have a question about searching the JSON for the specific information. For example, I have this JSON file:

 {
    "people": {
        "person": [
            {
                "name": "Peter",
                "age": 43,
                "sex": "male"
            }, {
                "name": "Zara",
                "age": 65,
                "sex": "female"
            }
        ]
    }
}

My question is, how can find a particular person by name and display that person's age with jQuery? For example, I want to search the JSON for a person called Peter and when I find a match I want to display additional information about that match (about person named Peter in this case) such as person's age for example.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
Mentalhead
  • 1,501
  • 5
  • 20
  • 28

11 Answers11

103
var json = {
    "people": {
        "person": [{
            "name": "Peter",
            "age": 43,
            "sex": "male"},
        {
            "name": "Zara",
            "age": 65,
            "sex": "female"}]
    }
};
$.each(json.people.person, function(i, v) {
    if (v.name == "Peter") {
        alert(v.age);
        return;
    }
});

Example.

Based on this answer, you could use something like:

$(function() {
    var json = {
        "people": {
            "person": [{
                "name": "Peter",
                "age": 43,
                "sex": "male"},
            {
                "name": "Zara",
                "age": 65,
                "sex": "female"}]
        }
    };
    $.each(json.people.person, function(i, v) {
        if (v.name.search(new RegExp(/peter/i)) != -1) {
            alert(v.age);
            return;
        }
    });
});

Example 2

Community
  • 1
  • 1
ifaour
  • 38,035
  • 12
  • 72
  • 79
  • Your example works pretty well, but I was wondering can I somehow use something like this: [link]http://api.jquery.com/attribute-equals-selector/ to find my match? – Mentalhead Mar 13 '11 at 11:30
  • 1
    One final question, is there a way to use standard jQuery selectors: [link]http://api.jquery.com/category/selectors/ to select and find the desired data or do I have to use the each() function? – Mentalhead Mar 13 '11 at 12:23
  • 1
    @Mentalhead: No, these methods are used to process DOM selectors. Also you want to loop over your object and the **correct** way to do so using jQuery is the **jQuery** method [jQuery.each()](http://api.jquery.com/jQuery.each/) – ifaour Mar 13 '11 at 12:26
  • 2
    I cant figure out how it is possible to replace `peter` in your expression with a variable?! I need to insert a string from `$(this).val()`. Any ideas? – yckart Aug 25 '12 at 12:04
  • Very simple and easy solution .. worked like a charm .. but definitely there is a need of proper JSON search functions. – UberNeo Oct 14 '13 at 20:30
  • tldr; **Thanks**... Longer Version: Not that I didn't know how to do it, I just wanted someone else to do the work for me. – Nabil Kadimi Nov 08 '15 at 16:59
  • I am stuck with replacing peter with a variable (like todays date from an input) – software is fun Feb 11 '17 at 02:14
  • Weird I cannot seem to return the current object when an value matches. Best i can do is hold it till the loop is complete then return it. Seems a bit sus. – carny666 May 16 '22 at 18:07
21

I found ifaour's example of jQuery.each() to be helpful, but would add that jQuery.each() can be broken (that is, stopped) by returning false at the point where you've found what you're searching for:

$.each(json.people.person, function(i, v) {
        if (v.name == "Peter") {
            // found it...
            alert(v.age);
            return false; // stops the loop
        }
});
Tapefreak
  • 982
  • 1
  • 13
  • 16
12

You could use Jsel - https://github.com/dragonworx/jsel (for full disclosure, I am the owner of this library).

It uses a real XPath engine and is highly customizable. Runs in both Node.js and the browser.

Given your original question, you'd find the people by name with:

// include or require jsel library (npm or browser)
var dom = jsel({
    "people": {
        "person": [{
            "name": "Peter",
            "age": 43,
            "sex": "male"},
        {
            "name": "Zara",
            "age": 65,
            "sex": "female"}]
    }
});
var person = dom.select("//person/*[@name='Peter']");
person.age === 43; // true

If you you were always working with the same JSON schema you could create your own schema with jsel, and be able to use shorter expressions like:

dom.select("//person[@name='Peter']")
Smily
  • 2,732
  • 1
  • 15
  • 20
Ali
  • 2,439
  • 23
  • 13
9

You can search on a json object array using $.grep() like this:

var persons = {
    "person": [
        {
            "name": "Peter",
            "age": 43,
            "sex": "male"
        }, {
            "name": "Zara",
            "age": 65,
            "sex": "female"
        }
      ]
   }
};
var result = $.grep(persons.person, function(element, index) {
   return (element.name === 'Peter');
});
alert(result[0].age);
Dexxo
  • 121
  • 1
  • 4
9

Once you have the JSON loaded into a JavaScript object, it's no longer a jQuery problem but is now a JavaScript problem. In JavaScript you could for instance write a search such as:

var people = myJson["people"];
var persons = people["person"];
for(var i=0; i < persons.length; ++i) {
    var person_i = persons[i];
    if(person_i["name"] == mySearchForName) {
        // found ! do something with 'person_i'.
        break;
    }
}
// not found !
DuckMaestro
  • 15,232
  • 11
  • 67
  • 85
  • Instead of `people["person"]` and `person_i["name"]` you can write `people.person` and `person_i.name` for short. – rsp Mar 13 '11 at 10:54
  • 2
    What do you mean by `it's no longer a jQuery problem but is now a JavaScript problem` ?! – ifaour Mar 13 '11 at 10:54
  • 2
    His question seemed to have the pretense (by my reading, though I could be wrong) that jQuery selectors can be used to traverse JSON, which they can't to my knowledge. So I mean "a JavaScript problem" in the sense that jQuery's primary function and selector capability doesn't apply. – DuckMaestro Mar 13 '11 at 20:59
9

There are some js-libraries that could help you with it:

You might also want to take a look at Lawnchair, which is a JSON-Document-Store which works in the browser and has all sorts of querying-mechanisms.

floer32
  • 2,190
  • 4
  • 29
  • 50
Martin Schuhfuß
  • 6,814
  • 1
  • 36
  • 44
  • There's also Jsel - https://github.com/dragonworx/jsel - it uses a real XPath engine and allows you to customize your schema so you can create better expressions if needed. – Ali Aug 13 '13 at 04:21
  • Lawnchair looks interesting .. any useful examples ?? – UberNeo Oct 14 '13 at 21:38
  • you can use the online interactive tool at http://dragonworx.github.io/jsel/ to try different expressions, there are some examples in the "XPath Examples" dropdown. – Ali Jan 21 '16 at 01:06
8

You can use DefiantJS (http://defiantjs.com) which extends the global object JSON with the method "search". With which you can query XPath queries on JSON structures. Example:

var byId = function(s) {return document.getElementById(s);},
data = {
   "people": {
      "person": [
         {
            "name": "Peter",
            "age": 43,
            "sex": "male"
         },
         {
            "name": "Zara",
            "age": 65,
            "sex": "female"
         }
      ]
   }
},
res = JSON.search( data, '//person[name="Peter"]' );

byId('name').innerHTML = res[0].name;
byId('age').innerHTML = res[0].age;
byId('sex').innerHTML = res[0].sex;

Here is a working fiddle;
http://jsfiddle.net/hbi99/NhL7p/

Hakan Bilgin
  • 1,113
  • 12
  • 11
2

I have kind of similar condition plus my Search Query not limited to particular Object property ( like "John" Search query should be matched with first_name and also with last_name property ). After spending some hours I got this function from Google's Angular project. They have taken care of every possible cases.

/* Seach in Object */

var comparator = function(obj, text) {
if (obj && text && typeof obj === 'object' && typeof text === 'object') {
    for (var objKey in obj) {
        if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
                comparator(obj[objKey], text[objKey])) {
            return true;
        }
    }
    return false;
}
text = ('' + text).toLowerCase();
return ('' + obj).toLowerCase().indexOf(text) > -1;
};

var search = function(obj, text) {
if (typeof text == 'string' && text.charAt(0) === '!') {
    return !search(obj, text.substr(1));
}
switch (typeof obj) {
    case "boolean":
    case "number":
    case "string":
        return comparator(obj, text);
    case "object":
        switch (typeof text) {
            case "object":
                return comparator(obj, text);
            default:
                for (var objKey in obj) {
                    if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
                        return true;
                    }
                }
                break;
        }
        return false;
    case "array":
        for (var i = 0; i < obj.length; i++) {
            if (search(obj[i], text)) {
                return true;
            }
        }
        return false;
    default:
        return false;
}
};
Hardik Sondagar
  • 4,347
  • 3
  • 28
  • 48
2
    var GDNUtils = {};

GDNUtils.loadJquery = function () {
    var checkjquery = window.jQuery && jQuery.fn && /^1\.[3-9]/.test(jQuery.fn.jquery);
    if (!checkjquery) {

        var theNewScript = document.createElement("script");
        theNewScript.type = "text/javascript";
        theNewScript.src = "http://code.jquery.com/jquery.min.js";

        document.getElementsByTagName("head")[0].appendChild(theNewScript);

        // jQuery MAY OR MAY NOT be loaded at this stage


    }
};



GDNUtils.searchJsonValue = function (jsonData, keytoSearch, valuetoSearch, keytoGet) {
    GDNUtils.loadJquery();
    alert('here' + jsonData.length.toString());
    GDNUtils.loadJquery();

    $.each(jsonData, function (i, v) {

        if (v[keytoSearch] == valuetoSearch) {
            alert(v[keytoGet].toString());

            return;
        }
    });



};




GDNUtils.searchJson = function (jsonData, keytoSearch, valuetoSearch) {
    GDNUtils.loadJquery();
    alert('here' + jsonData.length.toString());
    GDNUtils.loadJquery();
    var row;
    $.each(jsonData, function (i, v) {

        if (v[keytoSearch] == valuetoSearch) {


            row  = v;
        }
    });

    return row;



}
cindy
  • 21
  • 1
0

You don't have to use jQuery. Plain JavaScript will do. I wouldn't recommend any library that ports XML standards onto JavaScript, and I was frustrated that no other solution existed for this so I wrote my own library.

I adapted regex to work with JSON.

First, stringify the JSON object. Then, you need to store the starts and lengths of the matched substrings. For example:

"matched".search("ch") // yields 3

For a JSON string, this works exactly the same (unless you are searching explicitly for commas and curly brackets in which case I'd recommend some prior transform of your JSON object before performing regex (i.e. think :, {, }).

Next, you need to reconstruct the JSON object. The algorithm I authored does this by detecting JSON syntax by recursively going backwards from the match index. For instance, the pseudo code might look as follows:

find the next key preceding the match index, call this theKey
then find the number of all occurrences of this key preceding theKey, call this theNumber
using the number of occurrences of all keys with same name as theKey up to position of theKey, traverse the object until keys named theKey has been discovered theNumber times
return this object called parentChain

With this information, it is possible to use regex to filter a JSON object to return the key, the value, and the parent object chain.

You can see the library and code I authored at http://json.spiritway.co/

mikewhit
  • 121
  • 5
0

Traverse all the Nodes of a JSON Object Tree with JavaScript

Community
  • 1
  • 1
Luca Fagioli
  • 12,722
  • 5
  • 59
  • 57