3

我有一个包含一些 json 数据的变量 json。我正在尝试检索该数据的特定部分。我可以使用如下所示的索引来做到这一点:

var newdata = json[listid].Taxonomies[0];

但是我希望能够使用名称检索数据...例如,我想获取数据

json[listid].Taxonomies[?].InternalName = 'ABC'

而且我不知道“?”的价值

有没有一种方法可以在不对分类法进行每个循环的情况下做到这一点?

4

5 回答 5

1

这不能在没有循环的情况下完成,但是存在的库可以隐藏你的循环。

例如,使用JSPath您可以找到该InternalName属性的每个实例,而不管它的嵌套有多深:

> var json = { 1: { Taxonomies: [ { InternalName: 'ABC' } ] }}
> JSPath.apply('..InternalName', json);
["ABC"]
于 2013-04-16T19:41:09.640 回答
1

有人建议使用 linqjs,如果您需要大量 JSON 查询,这可能没问题。但是,对于这个问题,您可以使用Array.filter来指定要查找的项目。显然,引擎盖下仍然有一个循环。

var matches  = json[listid].Taxonomies.filter(function(obj) {
    return obj.InternalName === "ABC";
})

console.log(matches[0]);

http://jsfiddle.net/MC94q/

请注意,如果您担心性能,您应该使用对象而不是数组来表示数据,并且可以通过您将要搜索的属性对其进行键控。

如果我需要在数组上多次搜索,我使用的一个有用的功能如下。这会将数组转换为无需循环即可访问的映射。如果您担心性能,请尽可能以该格式生成数据。

/**
 * Creates a map by the given property to allow fast searches
 * @param {object[]} arr Array that we want to create a map from
 * @param {string} keyProp The property to key by
 * @param {boolean} [allowDuplicates] If this is true, the value
 *        of each key in the returned object will be an array with 
 *        all matches
 * @return A map keyed by the requested property. If the parameter 
 *         allowDuplicates is falsy, key property collisions will 
 *         overwrite the previous value. If the allowDuplicates is true,
 *         the map will have as its value an array of objects for the given key
 *
 * Example: Given the following array: arr=[{a:1, b:2}, {a:1, b:3}, {a:3, b:4)]
 *   The call to mapFromArray(arr, 'a') returns the following
 *          { 1: {a:1, b:3}, 3: {a:3, b:4} }
 *   Notice that {a:1,b:2} is not in the returned map because it has the 
 *   same value in the key property 'a' as {a:1, b:3}, which wins out 
 *   since it's later.
 *
 *   Calling  mapFromArray(arr, 'a', true) returns the following
  *         { 1: [{a:1, b:2}, {a:1, b:3}], 3: [{a:3, b:4}] }
 */
function mapFromArray(arr, keyProp, allowDuplicates) {
    var map = {};
    for (var i = 0, ln = arr.length; i < ln; i++) {
        if (!allowDuplicates) {
            // No duplicates allowed, may be overwriting an existing value
            map[arr[i][keyProp]] = arr[i];
        } else {
            // Duplicates are allowed, create array of matching objects
            // Ext.Array.push creates a one item array if its argument is
            // not already an array, otherwise, it pushes and returns the array
            map[arr[i][keyProp]] = Ext.Array.push(map[arr[i][keyProp]], arr[i]);
        }
    }
    return map;
}

因此,假设您想搜索具有InternalName“ABC”“DEF”“GHI”之一的分类法,您将执行以下操作:

var map = mapFromArray(json[listid].Taxonomies, "InternalName");
var ABC = map['ABC'], DEF = map['DEF'], GHI = map['GHI'];
于 2013-04-16T19:55:18.013 回答
0
var newdata = json[listid].Taxonomies.filter(function(el){
  return el.InternalName === "ABC";
})[0];

应该涵盖这样的对象的第一次出现。如果你想要一个包含所有出现的数组,你可以[0]在最后删除。

请注意,我假设一个嵌套级别,因为这就是问题的表述方式。如果您需要在任意深度数据结构中查找属性,这里的其他一些库可能更有意义。

于 2013-04-16T19:39:46.930 回答
0

首先想到的是 linqjs ( http://linqjs.codeplex.com/ )。这是给定您输入的示例。

var jsonArray = [
    { "listid": 1, 
     Taxaonomies:
        [ 
            { "id": 100, "InternalName": "d_linq" },
            { "id": 200, "InternalName": "fred" }
        ]
    },
    { "listid": 2, 
        Taxaonomies:
        [ 
            { "id": 100, "InternalName": "asdf" },
            { "id": 200, "InternalName": "qwer" }
        ]
    }
];

var queryResult = Enumerable.From(jsonArray)
    .Where(function (x) { 
        return Enumerable.From(x.Taxaonomies).Any(function (y) { return y.InternalName == "fred" }) 
    })
    .ToArray();

console.log(queryResult);

看到这个小提琴:http: //jsfiddle.net/alexdresko/3zsy9/

于 2013-04-16T19:48:18.103 回答
0

您可以使用 JQuery Javascript 库将 JSON 解析为对象。从那里您可以使用点语法访问属性。

http://api.jquery.com/jQuery.parseJSON/

var obj = jQuery.parseJSON('{"name":"Bob"}');
alert(obj.name === "Bob");
于 2013-04-16T20:43:11.300 回答