Py学习  »  Jquery

使用javascript jquery访问通过ajax返回的json数组中的嵌套键值[duplicate]

art vanderlay • 5 年前 • 2531 次点击  

我有一个包含对象和数组的嵌套数据结构。如何提取信息,即访问特定或多个值(或密钥)?

例如:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

我怎么能进入 name 中第二项的 items ?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/44029
 
2531 次点击  
文章 [ 22 ]  |  最新文章 5 年前
Machavity pradeep gowda
Reply   •   1 楼
Machavity pradeep gowda    7 年前

使用矿灰是个好办法

前任:

var object = { 'a': { 'b': { 'c': 3 } } };                                                                                               
_.get(object, 'a.b.c');                                                                                             
// => 3  
Kamil Kiełczewski
Reply   •   2 楼
Kamil Kiełczewski    6 年前

这里是动态方法-你的“深”键是string 'items[1].name' (可以使用数组表示法 [i] 在任何级别)-如果键无效,则返回未定义。

let deep = (o,k) => {
  return k.split('.').reduce((a,c,i) => {
    let m=c.match(/(.*?)\[(\d*)\]/);
    if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
    return a==null ? a: a[c];
  },o)
}

var data = {
    code: 42,
    items: [
      { id: 1, name: 'foo'}, 
      { id: 2, name: 'bar'},
   ]
};

let deep = (o,k) => {
  return k.split('.').reduce((a,c,i) => {
    let m=c.match(/(.*?)\[(\d*)\]/);
    if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
    return a==null ? a: a[c];
  },o)
}

console.log( deep(data,'items[1].name') );
Manthan Patel
Reply   •   3 楼
Manthan Patel    6 年前

我的 stringjson 来自php文件,但我在这里指出 var . 当我直接将json带入 obj 它不会显示这就是为什么我把json文件

var obj=JSON.parse(stringjson); 所以在那之后我得到 message obj并显示在警告框中,然后我得到 data 它是json数组,存储在一个变量中 ArrObj 然后我读取数组的第一个对象,其键值如下 ArrObj[0].id

     var stringjson={
        "success": true,
        "message": "working",
        "data": [{
                  "id": 1,
                  "name": "foo"
         }]
      };

                var obj=JSON.parse(stringjson);
                var key = "message";
                alert(obj[key]);
                var keyobj = "data";
                var ArrObj =obj[keyobj];

                alert(ArrObj[0].id);
user7110739
Reply   •   4 楼
user7110739    8 年前

jQuery's grep 函数用于筛选数组:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

$.grep(data.items, function(item) {
    if (item.id === 2) {
        console.log(item.id); //console id of item
        console.log(item.name); //console name of item
        console.log(item); //console item object
        return item; //returns item object
    }

});
// Object {id: 2, name: "bar"}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
pX0r
Reply   •   5 楼
pX0r    8 年前

解析任意json树的python、递归和函数方法:

handlers = {
    list:  iterate,
    dict:  delve,
    str:   emit_li,
    float: emit_li,
}

def emit_li(stuff, strong=False):
    emission = '<li><strong>%s</strong></li>' if strong else '<li>%s</li>'
    print(emission % stuff)

def iterate(a_list):
    print('<ul>')
    map(unravel, a_list)
    print('</ul>')

def delve(a_dict):
    print('<ul>')
    for key, value in a_dict.items():
        emit_li(key, strong=True)
        unravel(value)
    print('</ul>')

def unravel(structure):
    h = handlers[type(structure)]
    return h(structure)

unravel(data)

哪里 数据 是一个python列表(从json文本字符串解析):

data = [
    {'data': {'customKey1': 'customValue1',
           'customKey2': {'customSubKey1': {'customSubSubKey1': 'keyvalue'}}},
  'geometry': {'location': {'lat': 37.3860517, 'lng': -122.0838511},
               'viewport': {'northeast': {'lat': 37.4508789,
                                          'lng': -122.0446721},
                            'southwest': {'lat': 37.3567599,
                                          'lng': -122.1178619}}},
  'name': 'Mountain View',
  'scope': 'GOOGLE',
  'types': ['locality', 'political']}
]
Dinesh Pandiyan
Reply   •   6 楼
Dinesh Pandiyan    7 年前

以防万一,任何人在2017年或以后访问此问题,并寻找 容易记住 好的,这里有一篇详细的博客文章 Accessing Nested Objects in JavaScript 不会被愚弄

无法读取未定义的属性“foo” 错误

1。奥利弗·斯蒂尔的嵌套对象访问模式

最简单和最干净的方法是使用oliver steele的嵌套对象访问模式

const name = ((user || {}).personalInfo || {}).name;

用这个符号,你永远不会碰到

无法读取未定义的属性“name” .

你基本上检查用户是否存在,如果不存在,你就动态地创建一个空对象。这样,下一级键将 总是从存在的对象或空对象访问 ,但从未从未定义开始。

2。使用array reduce访问嵌套对象

为了能够访问嵌套数组,可以编写自己的数组,减少UTIL。

const getNestedObject = (nestedObj, pathArr) => {
    return pathArr.reduce((obj, key) =>
        (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}

// pass in your object structure as array elements
const name = getNestedObject(user, ['personalInfo', 'name']);

// to access nested array, just pass in array index as an element the path array.
const city = getNestedObject(user, ['personalInfo', 'addresses', 0, 'city']);
// this will return the city from the first address item.

还有一个优秀的类型处理最小库 typy 这一切都是为了你。

Ilyas karim Andrei Todorut
Reply   •   7 楼
Ilyas karim Andrei Todorut    7 年前

动态访问多级对象。

var obj = {
  name: "salut",
  subobj: {
    subsubobj: {
      names: "I am sub sub obj"
    }
  }
};

var level = "subobj.subsubobj.names";
level = level.split(".");

var currentObjState = obj;

for (var i = 0; i < level.length; i++) {
  currentObjState = currentObjState[level[i]];
}

console.log(currentObjState);

工作小提琴: https://jsfiddle.net/andreitodorut/3mws3kjL/

dabeng
Reply   •   8 楼
dabeng    8 年前

我不认为questizer只关心一个层次的嵌套对象,所以我展示了下面的演示来演示如何访问深嵌套json对象的节点。好吧,让我们找到ID为“5”的节点。

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'aaa',
    items: [{
        id: 3,
        name: 'ccc'
      }, {
        id: 4,
        name: 'ddd'
      }]
    }, {
    id: 2,
    name: 'bbb',
    items: [{
        id: 5,
        name: 'eee'
      }, {
        id: 6,
        name: 'fff'
      }]
    }]
};

var jsonloop = new JSONLoop(data, 'id', 'items');

jsonloop.findNodeById(data, 5, function(err, node) {
  if (err) {
    document.write(err);
  } else {
    document.write(JSON.stringify(node, null, 2));
  }
});
<script src="https://rawgit.com/dabeng/JSON-Loop/master/JSONLoop.js"></script>
Thiago C. S Ventura
Reply   •   9 楼
Thiago C. S Ventura    8 年前

老问题,但没有人提到洛达斯(只是强调)。

如果您已经在您的项目中使用了lodash,我想在一个复杂的示例中可以用一种优雅的方法来实现这一点:

选择1

_.get(response, ['output', 'fund', 'data', '0', 'children', '0', 'group', 'myValue'], '')

等同于:

选择2

response.output.fund.data[0].children[0].group.myValue

第一个和第二个选项的区别在于 选择1 如果路径中缺少(未定义)某个属性,则不会出现错误,它将返回第三个参数。

对于阵列滤波器,lodash有 _.find() 但我宁愿用普通的 filter() . 但我还是认为上面的方法 _.get() 在处理非常复杂的数据时非常有用。我过去面对的是复杂的API,很方便!

我希望它能对WHO正在寻找选项来操纵真正复杂的数据,这是标题所暗示的。

Mohan Dere
Reply   •   10 楼
Mohan Dere    9 年前

下划线js方式

它是一个javascript库,提供了一大堆有用的 functional programming 不扩展任何内置对象的帮助程序。

解决方案:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

var item = _.findWhere(data.items, {
  id: 2
});
if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}

//using find - 

var item = _.find(data.items, function(item) {
  return item.id === 2;
});

if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}
Bergi
Reply   •   11 楼
Bergi    10 年前

如果要查找满足特定条件的一个或多个对象,可以使用 query-js

//will return all elements with an id larger than 1
data.items.where(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
data.items.first(function(e){return e.id > 1;});
//will return the first element with an id larger than 1 
//or the second argument if non are found
data.items.first(function(e){return e.id > 1;},{id:-1,name:""});

还有一个 single 和A singleOrDefault 他们的工作方式很像 first firstOrDefault 分别是。唯一的区别是如果 更多 找到多个匹配项。

有关查询JS的进一步解释,您可以从这里开始 post

Johnny
Reply   •   12 楼
Johnny    6 年前
var ourStorage = {


"desk":    {
    "drawer": "stapler"
  },
"cabinet": {
    "top drawer": { 
      "folder1": "a file",
      "folder2": "secrets"
    },
    "bottom drawer": "soda"
  }
};
ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"

//parent.subParent.subsubParent["almost there"]["final property"]

基本上,在展开的每个子代之间使用一个点,当对象名由两个字符串组成时,必须使用[“obj name”]表示法。否则,只要一个点就足够了;

来源: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects

要添加此项,访问嵌套数组的方式如下:

var ourPets = [
  {
    animalType: "cat",
    names: [
      "Meowzer",
      "Fluffy",
      "Kit-Cat"
    ]
  },
  {
    animalType: "dog",
    names: [
      "Spot",
      "Bowser",
      "Frankie"
    ]
  }
];
ourPets[0].names[1]; // Outputs "Fluffy"
ourPets[1].names[0]; // Outputs "Spot"

来源: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/

另一份描述上述情况的更有用的文件: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

通过点行走访问属性: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation

Koby Douek Ramakrishna
Reply   •   13 楼
Koby Douek Ramakrishna    8 年前

你可以用 lodash _get 功能:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// => 3
Rudy Hinojosa
Reply   •   14 楼
Rudy Hinojosa    9 年前

我更喜欢jquery。它干净易读。

 $.each($.parseJSON(data), function (key, value) {
    alert(value.<propertyname>);
});
Andrejs
Reply   •   15 楼
Andrejs    11 年前

使用 JSONPATH 如果您愿意包括一个库,这将是最灵活的解决方案之一: https://github.com/s3u/JSONPath (节点和浏览器)

对于您的用例,json路径将是:

$..items[1].name

所以:

var secondName = jsonPath.eval(data, "$..items[1].name");
Evgeny
Reply   •   16 楼
Evgeny    7 年前

要访问嵌套属性,需要指定其名称,然后在对象中搜索。

如果你已经知道确切的路径,那么你可以像你这样在脚本中硬编码:

data['items'][1]['name']

这些也起作用-

data.items[1].name
data['items'][1].name
data.items[1]['name']

当你在手之前不知道确切的名字,或者用户是为你提供名字的人。然后需要通过数据结构进行动态搜索。有些人建议可以使用 for 循环,但有一种非常简单的方法可以使用 Array.reduce .

const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }
const path = [ 'items', '1', 'name']
let result = path.reduce((a,v) => a[v], data)

路径是这样说的:首先取带键的对象 items ,这正好是一个数组。那就拿着 1 -st元素(0个索引数组)。最后一个带键的对象 name 在数组元素中,正好是字符串 bar .

如果你有很长的路,你甚至可以使用 String.split 让这一切变得更容易-

'items.1.name'.split('.').reduce((a,v) => a[v], data)

这只是简单的javascript,没有使用任何第三方库,如jquery或lodash。

Jon Chesterfield Alex KeySmith
Reply   •   17 楼
Jon Chesterfield Alex KeySmith    9 年前

这个问题已经很老了,所以作为当代的更新。随着ES2015的开始,有其他方法可以获得所需的数据。现在有一个特性叫做 对象解构 用于访问嵌套对象。

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

const {
  items: [, {
    name: secondName
  }]
} = data;

console.log(secondName);

上面的例子创建了一个名为 secondName name 来自名为 items 孤独的人 , 表示跳过数组中的第一个对象。

值得注意的是,对于这个例子来说,它可能有点过头了,因为简单的数组访问更容易阅读,但是它在一般情况下分解对象时非常有用。

这是非常简短的介绍你的具体用例,破坏可以是一个不寻常的语法首先习惯。我建议你读书 Mozilla's Destructuring Assignment documentation 去了解更多。

Michał Perłakowski Khoa Bui
Reply   •   18 楼
Michał Perłakowski Khoa Bui    8 年前

对象和数组有很多内置的方法,可以帮助您处理数据。

注意:在我使用的许多例子中 arrow functions . 它们类似于 function expressions ,但它们将 this 重视词汇。

Object.keys() , Object.values() (ES 2017)和 Object.entries() (ES 2017)

object.keys() 返回对象键的数组, object.values() 返回对象值的数组,并且 object.entries() 以某种格式返回对象键和相应值的数组 [key, value] .

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

console.log(Object.keys(obj)) // ['a', 'b', 'c']
console.log(Object.values(obj)) // [1, 2, 3]
console.log(Object.entries(obj)) // [['a', 1], ['b', 2], ['c', 3]]

object.entries() 带for循环和解构赋值

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

for (const [key, value] of Object.entries(obj)) {
  console.log(`key: ${key}, value: ${value}`)
}

迭代 object.entries() 用一个 for-of loop destructuring assignment .

for of循环允许您迭代数组元素。语法是 for (const element of array) 我们可以替代 const 具有 var let ,但最好使用 康斯特 如果我们不打算修改 element )

解构赋值允许您从数组或对象中提取值并将它们赋给变量。在这种情况下 const [key, value] 也就是说,不是指定 [关键,价值] 数组到 要素 ,我们将该数组的第一个元素分配给 key 第二个元素 value . 相当于:

for (const element of Object.entries(obj)) {
  const key = element[0]
       ,value = element[1]
}

正如你所看到的,破坏使这更简单。

Array.prototype.every() Array.prototype.some()

这个 every() 方法返回 true 如果指定的回调函数返回 对于 每一个 数组的元素。这个 some() 方法返回 如果指定的回调函数返回 对于 一些 (至少一个)元素。

const arr = [1, 2, 3]

// true, because every element is greater than 0
console.log(arr.every(x => x > 0))
// false, because 3^2 is greater than 5
console.log(arr.every(x => Math.pow(x, 2) < 5))
// true, because 2 is even (the remainder from dividing by 2 is 0)
console.log(arr.some(x => x % 2 === 0))
// false, because none of the elements is equal to 5
console.log(arr.some(x => x === 5))

Array.prototype.find() Array.prototype.filter()

这个 find() 方法返回 第一 满足所提供回调函数的元素。这个 filter() 方法返回 全部的 满足所提供回调函数的元素。

const arr = [1, 2, 3]

// 2, because 2^2 !== 2
console.log(arr.find(x => x !== Math.pow(x, 2)))
// 1, because it's the first element
console.log(arr.find(x => true))
// undefined, because none of the elements equals 7
console.log(arr.find(x => x === 7))

// [2, 3], because these elements are greater than 1
console.log(arr.filter(x => x > 1))
// [1, 2, 3], because the function returns true for all elements
console.log(arr.filter(x => true))
// [], because none of the elements equals neither 6 nor 7
console.log(arr.filter(x => x === 6 || x === 7))

Array.prototype.map()

这个 map() 方法返回一个数组,其中包含对数组元素调用提供的回调函数的结果。

const arr = [1, 2, 3]

console.log(arr.map(x => x + 1)) // [2, 3, 4]
console.log(arr.map(x => String.fromCharCode(96 + x))) // ['a', 'b', 'c']
console.log(arr.map(x => x)) // [1, 2, 3] (no-op)
console.log(arr.map(x => Math.pow(x, 2))) // [1, 4, 9]
console.log(arr.map(String)) // ['1', '2', '3']

Array.prototype.reduce()

这个 reduce() 方法通过使用两个元素调用提供的回调函数将数组缩减为单个值。

const arr = [1, 2, 3]

// Sum of array elements.
console.log(arr.reduce((a, b) => a + b)) // 6
// The largest number in the array.
console.log(arr.reduce((a, b) => a > b ? a : b)) // 3

这个 约化() 方法接受可选的第二个参数,即初始值。当您调用的数组 约化() 可以有零或一个元素。例如,如果我们想要创建一个函数 sum() 它接受一个数组作为参数并返回所有元素的和,我们可以这样写:

const sum = arr => arr.reduce((a, b) => a + b, 0)

console.log(sum([]))     // 0
console.log(sum([4]))    // 4
console.log(sum([2, 5])) // 7
Community samael
Reply   •   19 楼
Community samael    8 年前

有时,使用字符串访问嵌套对象是可取的。简单的方法是第一个层次,例如

var obj = { hello: "world" };
var key = "hello";
alert(obj[key]);//world

但对于复杂的json,情况往往并非如此。随着json变得更加复杂,在json中查找值的方法也变得复杂。导航json的递归方法是最好的,如何利用递归取决于搜索的数据类型。如果涉及条件语句,则 json search 可以很好的使用工具。

如果要访问的属性已知,但路径很复杂,例如在这个对象中

var obj = {
 arr: [
    { id: 1, name: "larry" },    
    { id: 2, name: "curly" },
    { id: 3, name: "moe" }
 ]
};

你知道你想得到对象中数组的第一个结果,也许你想使用

var moe = obj["arr[0].name"];

但是,这将导致异常,因为没有具有该名称的对象的属性。能够使用它的解决方案是将对象的树方面展平。这可以递归地完成。

function flatten(obj){
 var root = {};
 (function tree(obj, index){
   var suffix = toString.call(obj) == "[object Array]" ? "]" : "";
   for(var key in obj){
    if(!obj.hasOwnProperty(key))continue;
    root[index+key+suffix] = obj[key];
    if( toString.call(obj[key]) == "[object Array]" )tree(obj[key],index+key+suffix+"[");
    if( toString.call(obj[key]) == "[object Object]" )tree(obj[key],index+key+suffix+".");   
   }
 })(obj,"");
 return root;
}

现在,复杂的物体可以变平。

var obj = previous definition;
var flat = flatten(obj);
var moe = flat["arr[0].name"];//moe

这里是一个 jsFiddle Demo 使用这种方法。

lukas.pukenis holographic-prin
Reply   •   20 楼
lukas.pukenis holographic-prin    11 年前

如果你想访问 item 从示例结构 id name ,不知道它在数组中的位置,最简单的方法是使用 underscore.js 图书馆:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

_.find(data.items, function(item) {
  return item.id === 2;
});
// Object {id: 2, name: "bar"}

根据我的经验,用高阶函数代替 for for..in 循环产生的代码更容易推理,因此更易于维护。

就我的2美分。