2013-04-16 177 views
3

我有一个包含一些json数据的变量json。我正在尝试检索该数据的特定部分。我可以使用索引做这样所示:从json获取特定数据

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

不过,我希望能够用一个名字来检索数据... 比如我想要得到的数据,其中

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

,我不知道'?'的价值

有没有一种方法可以做到这一点,而不需要在分类法上做每个循环?

+2

没有循环?有趣。 –

+0

json [listid] .Taxonomies [var] ??? –

+0

基于我知道的内部名称的值。 – BlueBird

回答

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

所以说你想搜索的分类与“ABC”'DEF“GHI”之一的InternalName,你会做以下几点:

var map = mapFromArray(json[listid].Taxonomies, "InternalName"); 
var ABC = map['ABC'], DEF = map['DEF'], GHI = map['GHI']; 
0
var newdata = json[listid].Taxonomies.filter(function(el){ 
    return el.InternalName === "ABC"; 
})[0]; 

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

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

1

这不能没有循环就可以完成,但存在隐藏循环的库。

例如,使用JSPath你可以找到InternalName财产的每个实例,无论它是多么深的嵌套:

> var json = { 1: { Taxonomies: [ { InternalName: 'ABC' } ] }} 
> JSPath.apply('..InternalName', json); 
["ABC"] 
+0

是否有理由使用本机过滤函数库? –

+1

@ ben336它取决于 - 如果您不知道结构有多深,则JSPath仍可以处理它。 '.filter'不会。 – Alnitak

+1

+1只是我从这里发现了JSPath。 Freakin'真棒! – Kushal

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/

+0

yeuch。这怎么比JSPath更简单或者只是使用JS的内置枚举和过滤函数进行迭代? – Alnitak

+0

linqjs比我所演示的更加强大,我几乎可以保证用linqjs做比使用本地js更复杂的东西会更容易。 PLUS,linqjs很容易学习,如果你已经熟悉.NET中的linq。 :) –

0

您可以使用jQuery JavaScript库将JSON解析为一个对象。从那里你可以使用点语法访问属性。

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

var obj = jQuery.parseJSON('{"name":"Bob"}'); 
alert(obj.name === "Bob");