嵌套的JSON查找项

时间:2014-05-04 18:51:43

标签: javascript jquery json

我有以下有效的JSON。它描述了一个树结构:

{
"items": [
    {
        "id": "d1"
    },
    {
        "id": "2",
        "children": [
            {
                "id": "3"
            },
            {
                "id": "4"
            },
            {
                "id": "5",
                "children": [
                    {
                        "id": "6"
                    },
                    {
                        "id": "7",
                        "children": [
                            {
                                "id": "8"
                            },
                            {
                                "id": "9"
                            }
                        ]
                    },
                    {
                        "id": "10"
                    }
                ]
            },
            {
                "id": "11"
            },
            {
                "id": "12"
            }
        ]
    },
    {
        "id": "13"
    },
    {
        "id": "14"
    }
]
}

我需要能够通过id和任何子项获取任何“项目”。例如。最初我尝试了grep:

var returnedData = $.grep(obj.items, function(element, index){return element.id == "2";
});

这对于id == 2的项目非常有用,但在我尝试获取element.id ==“7”时完全失败

任何帮助将不胜感激。提前谢谢。

3 个答案:

答案 0 :(得分:4)

您可以创建一个递归函数来搜索数据:

function find(source, id)
{
    for (key in source)
    {
        var item = source[key];
        if (item.id == id)
            return item;

        // Item not returned yet. Search its children by recursive call.
        if (item.children)
        {
            var subresult = find(item.children, id);

            // If the item was found in the subchildren, return it.
            if (subresult)
                return subresult;
        }
    }
    // Nothing found yet? return null.
    return null;
}

// In the root object, the array of items is called 'items', so we pass in 
// data.items to look into. The root object itself doesn't seem to have an id anyway.
var result = find(data.items, 7);

// Show the name of item 7, if it had one... 
alert(result.name);

演示:http://jsfiddle.net/rj26H/

在这个函数中,我只是在对象上循环,所以它有点冗长。您也可以使用$ .grep进行搜索并使代码更小一些。无论如何,诀窍是搜索所有孩子,如果在主级别找不到该项目。显然grep没有以递归的方式工作。

答案 1 :(得分:1)

试试这个:

var id = 7;
var data = {"items": [{"id": "d1"},{"id": "2","children": [{"id": "3"},{"id": "7"},{"id": "11"},{"id": "12"}]}]};
function search(values) {
    $.each(values, function(i, v) {
        if (v.id == id) { 
           console.log('found', v);
           return false;
        }
        if (v.children) {
            search(v.children);
        }
    });
}
search(data.items);

Demo Link

答案 2 :(得分:0)

我知道这已经得到了回答,但我想展示一下如何利用新的JavaScript 1.7 features来解决这个问题。请注意,在不支持生成器的情况下可以使用相同的方法,但代码会更长。

//Returns an iterator that knows how to walk a tree
function treeIterator(root, childGetter, childCountGetter) {
    let stack = [root], node;

    while (node = stack.pop()) {
        yield node;

        for (let i = childCountGetter(node); i--;) stack.push(childGetter(node, i));
    }
}

//Our custom search function
function findNodeById(tree, id) {
    let it = treeIterator(tree, 
        function (node, i) { return node.children[i]; },
        function (node) { return node.children? node.children.length : 0; }
    );

    for (let node in it) if (node.id === id) return node;

    return null;
}

var tree = {
    id: 'root',
    children: [
        { id: 'a' },
        {
            id: 'b',
            children: [
                { id: 'b1' },
                { id: 'b2' }
            ]
        },
        { id: 'c' }
    ]
};

findNodeById(tree, 'b1'); //Object { id="b1"}

请注意,您还可以在数据结构上设置__iterator__,以便需要迭代此数据结构的函数不必知道实现细节。

tree.__iterator__ = treeIterator.bind(null, tree, 
    function (node, i) { return node.children[i]; },
    function (node) { return node.children? node.children.length : 0; }
);

然后findNodeById函数可以是:

function findNodeById(tree, id) {
    for (let node in it) if (node.id === id) return node;
    return null;
}