在JSON对象上使用jQuery的find()


73

brnwdrng的问题类似,我正在寻找一种搜索类似于JSON的对象的方法。
假设我对象的结构是这样的:

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."
    }]
};

我想获得一个id =“ A”的对象。

我已经尝试过各种方法,例如:

$(TestObj.find(":id='A'"))

但似乎没有任何效果。

任何人都可以想到一种无需使用“每个”即可根据某些条件检索项目的方法吗?


2
1.您有一个普通的JavaScript对象,而不是类似JSON的对象。您只需要使用对象文字符号来定义它,JSON只是其中的一部分(但是JSON在完全不同的上下文中工作)。benalman.com/news/2010/03/theres-no-such-thing-as-a-json 2. jQuery在DOM上起作用,而不在任意对象上起作用。您为该工作使用了错误的工具。除了遍历产品数组,没有其他方法。
Felix Kling

Answers:


119

jQuery不适用于普通对象文字。您可以类似的方式使用以下函数来搜索所有“ id”(或任何其他属性),而不管其在对象中的深度如何:

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;
}

像这样使用:

getObjects(TestObj, 'id', 'A'); // Returns an array of matching objects

2
它不是JSON对象。这也意味着您要遍历for...in应该避免的数组...
Felix Kling

@Felix,是的,您将使用循环遍历数组for...in,但是当给定任意对象时,不能保证其中的任何数组都将是“ true”数组。即使您检查构造函数,某些方法(例如slice等等),仍然会有expando属性,因此我看不出进一步定义逻辑的意义。
大卫·唐

@ Box9:是的,可能不值得付出努力。只是说这可能会导致意外的结果。但检测阵列应该努力通过确定Object.prototype.toString.call(obj)这将使[object Array]
Felix Kling

1
@Felix,我想这取决于您想要什么作为Arrays的预期结果。即使通常创建一个数组([]),您仍然可以向其中添加(非数字)属性,您可能想要或可能不想对其进行迭代。除此之外,检查还hasOwnProperty()可以防止迭代原型中的属性。
David Tang

1
@ Box9:是的。似乎我专注于for...in和数组,但我并没有真正意识到你在做什么hasOwnProperty()……没关系,我把所有东西都拿回来了;)和+1作为赎回:o)
Felix Kling,

50

纯粹的javascript解决方案更好,但是jQuery的方式是使用jQuery grep和/或map方法。可能并不比使用$ .each好得多

jQuery.grep(TestObj, function(obj) {
    return obj.id === "A";
});

要么

jQuery.map(TestObj, function(obj) {
    if(obj.id === "A")
         return obj; // or return obj.name, whatever.
});

返回匹配对象的数组,如果是map,则返回查找值的数组。只需使用这些功能,便可以做您想做的事情。

但是在此示例中,您将必须进行一些递归,因为数据不是平面数组,并且我们接受任意结构,键和值,就像纯JavaScript解决方案一样。

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;
}

本质上与Box9的答案相同,但是在有用的地方使用jQuery实用程序函数。

········


2
我用这一个 jQuery.grep(TestObj, function(obj) { return obj.id === "A"; })[0].PropertyName;
路易斯·罗伯斯

3
对于使用的用户$.grep(),请记住它返回一个数组。这意味着如果您正在寻找单个物品,则需要使用它才能使用$.grep(/* whatever */)[0]
Jason 2012年

1
$ .grep()只是为我省去了一个巨大的头痛。我的问题/解决方案与OP无关,但这使我只查询一次数据库,而不是n次。太棒了!
erbaker 2012年

@davepncj如果我比较字符串,则字符串在对象字符串中有一个字母小,而在比较字符串中一个字母大写的区别。那我们怎么能忍受这种差异(小写和大写字母)
Bhavin Thummar

5

这对我来说适用于[{“ 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;
}

3

对于一维json,您可以使用以下代码:

function exist (json, modulid) {
    var ret = 0;
    $(json).each(function(index, data){
        if(data.modulId == modulid)
            ret++;
    })
    return ret > 0;
}

2

您可以使用JSONPath

做这样的事情:

results = JSONPath(null, TestObj, "$..[?(@.id=='A')]")

请注意,JSONPath返回结果数组

(我尚未测试过表达式“ $ .. [?(@。id =='A')]”)顺便说一句。也许需要借助浏览器控制台对其进行微调)


-4

我想提到的另一个选择是,您可以将数据转换为XML,然后使用jQuery.find(":id='A'")所需的方式。

有实现此效果的jQuery插件,例如json2xml

可能不值得转换开销,但是对于静态数据来说这是一次性的成本,因此它可能很有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.