use jQuery's find() on JSON object
Similar to brnwdrng's question, I'm looking for a way to search through a JSON-like object.
supposing my object's structure is like so:TestObj = {
"Categories": [{
"Products": [{
"id": "a01",
"name": "Pine",
"description": "Short description of pine."
},
{
"id": "a02",
"name": "Birch",
"description": "Short description of birch."
},
{
"id": "a03",
"name": "Poplar",
"description": "Short description of poplar."
}],
"id": "A",
"title": "Cheap",
"description": "Short description of category A."
},
{
"Product": [{
"id": "b01",
"name": "Maple",
"description": "Short description of maple."
},
{
"id": "b02",
"name": "Oak",
"description": "Short description of oak."
},
{
"id": "b03",
"name": "Bamboo",
"description": "Short description of bamboo."
}],
"id": "B",
"title": "Moderate",
"description": "Short description of category B."
}]
};
I'd like to get an object with id="A".
I've tried all sort of stuff such as:
$(TestObj.find(":id='A'"))
but nothing seems t开发者_运维技巧o work.
Can anyone think of a way of retrieving an item based on some criteria without using 'each'?
jQuery doesn't work on plain object literals. You can use the below function in a similar way to search all 'id's (or any other property), regardless of its depth in the object:
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
}
Use like so:
getObjects(TestObj, 'id', 'A'); // Returns an array of matching objects
The pure javascript solution is better, but a jQuery way would be to use the jQuery grep and/or map methods. Probably not much better than using $.each
jQuery.grep(TestObj, function(obj) {
return obj.id === "A";
});
or
jQuery.map(TestObj, function(obj) {
if(obj.id === "A")
return obj; // or return obj.name, whatever.
});
Returns an array of the matching objects, or of the looked-up values in the case of map. Might be able to do what you want simply using those.
But in this example you'd have to do some recursion, because the data isn't a flat array, and we're accepting arbitrary structures, keys, and values, just like the pure javascript solutions do.
function getObjects(obj, key, val) {
var retv = [];
if(jQuery.isPlainObject(obj))
{
if(obj[key] === val) // may want to add obj.hasOwnProperty(key) here.
retv.push(obj);
var objects = jQuery.grep(obj, function(elem) {
return (jQuery.isArray(elem) || jQuery.isPlainObject(elem));
});
retv.concat(jQuery.map(objects, function(elem){
return getObjects(elem, key, val);
}));
}
return retv;
}
Essentially the same as Box9's answer, but using the jQuery utility functions where useful.
········
This works for me on [{"id":"data"},{"id":"data"}]
function getObjects(obj, key, val)
{
var newObj = false;
$.each(obj, function()
{
var testObject = this;
$.each(testObject, function(k,v)
{
//alert(k);
if(val == v && k == key)
{
newObj = testObject;
}
});
});
return newObj;
}
For one dimension json you can use this:
function exist (json, modulid) {
var ret = 0;
$(json).each(function(index, data){
if(data.modulId == modulid)
ret++;
})
return ret > 0;
}
You can use JSONPath
Doing something like this:
results = JSONPath(null, TestObj, "$..[?(@.id=='A')]")
Note that JSONPath returns an array of results
(I have not tested the expression "$..[?(@.id=='A')]" btw. Maybe it needs to be fine-tuned with the help of a browser console)
Another option I wanted to mention, you could convert your data into XML and then use jQuery.find(":id='A'")
the way you wanted.
There are jQuery plugins to that effect, like json2xml.
Probably not worth the conversion overhead, but that's a one time cost for static data, so it might be useful.
精彩评论