我有一个包含对象和数组的嵌套数据结构。我如何提取信息,即访问一个特定的或多个值(或键)?
例如:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
我如何访问项目中的第二个项目的名称?
我有一个包含对象和数组的嵌套数据结构。我如何提取信息,即访问一个特定的或多个值(或键)?
例如:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
我如何访问项目中的第二个项目的名称?
当前回答
下面是一个使用对象扫描的答案。
当访问单个条目时,这个答案并没有提供比普通javascript更多的好处。然而,同时与多个字段交互,这个答案可以更有效。
下面是与单个字段交互的方法
// const objectScan = require('object-scan'); const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }; const get = (haystack, needle) => objectScan([needle], { abort: true, rtn: 'value' })(haystack); const set = (haystack, needle, value) => objectScan([needle], { abort: true, rtn: 'bool', filterFn: ({ parent, property }) => { parent[property] = value; return true; } })(haystack); console.log(get(data, 'items[1].name')); // => bar console.log(set(data, 'items[1].name', 'foo2')); // => true console.log(data); // => { code: 42, items: [ { id: 1, name: 'foo' }, { id: 2, name: 'foo2' } ] } .as-console-wrapper {max-height: 100% !important; top: 0} <script src="https://bundle.run/object-scan@13.8.0"></script>
声明:我是object-scan的作者
下面是如何同时与多个字段交互
// const objectScan = require('object-scan'); const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }; const get = (haystack, ...needles) => objectScan(needles, { joined: true, rtn: 'entry' })(haystack); const set = (haystack, actions) => objectScan(Object.keys(actions), { rtn: 'count', filterFn: ({ matchedBy, parent, property }) => { matchedBy.forEach((m) => { parent[property] = actions[m]; }) return true; } })(haystack); console.log(get(data, 'items[0].name', 'items[1].name')); // => [ [ 'items[1].name', 'bar' ], [ 'items[0].name', 'foo' ] ] console.log(set(data, { 'items[0].name': 'foo1', 'items[1].name': 'foo2' })); // => 2 console.log(data); // => { code: 42, items: [ { id: 1, name: 'foo1' }, { id: 2, name: 'foo2' } ] } .as-console-wrapper {max-height: 100% !important; top: 0} <script src="https://bundle.run/object-scan@13.8.0"></script>
声明:我是object-scan的作者
下面是如何在一个深度嵌套的对象中通过id搜索找到一个实体(正如在评论中问到的那样)
// const objectScan = require('object-scan'); const myData = { 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' }] }] }; const findItemById = (haystack, id) => objectScan(['**(^items$).id'], { abort: true, useArraySelector: false, rtn: 'parent', filterFn: ({ value }) => value === id })(haystack); console.log(findItemById(myData, 5)); // => { id: 5, name: 'eee' } .as-console-wrapper {max-height: 100% !important; top: 0} <script src="https://bundle.run/object-scan@13.8.0"></script>
声明:我是object-scan的作者
其他回答
动态方法
在下面的deep(data,key)函数中,您可以使用任意键字符串-在您的情况下,items[1].name(您可以在任何级别使用数组符号[i]) -如果key无效,则返回undefined。
让深= (o, k) = > k.split (' . ') .reduce ((a、c、i) = > { 让m = c.match (/(.*?)\[(\ d *) \] /); 如果(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]]; 返回a==null ?答:[c]; }, o); / /测试 Let key = 'items[1].name' //任意深键 Let data = { 42岁的代码: 名称:项目:[{id: 11日“foo”},{id: 22岁的名字:“酒吧”},) }; Console.log (key,'=', deep(data,key));
使用lodash是一个很好的解决方案
例:
var object = { 'a': { 'b': { 'c': 3 } } };
_.get(object, 'a.b.c');
// => 3
解释很简单:
Var数据= { 42岁的代码: 项目:[{ id: 1、 名称:“foo” }, { id: 2 名称:“酒吧” }) }; /* 1. “data”对象包含“items”对象*/ console.log(数据); /* 2. ' items '对象包含两个对象作为元素的数组*/ console.log (data.items); /* 3.你需要数组的第二个元素-从'[0,1]' */中的' 1 ' console.log (data.items [1]); /* 4. 你需要第二个对象的' name '属性的值-数组的元素)*/ console.log (data.items [1] . name);
老问题,但没有人提到lodash(只是下划线)。
如果你已经在你的项目中使用lodash,我认为在一个复杂的例子中有一种优雅的方法:
选择1
_.get(response, ['output', 'fund', 'data', '0', 'children', '0', 'group', 'myValue'], '')
一样:
选择2
response.output.fund.data[0].children[0].group.myValue
第一个选项和第二个选项之间的区别是,在Opt 1中,如果你在路径中缺少一个属性(未定义),你不会得到错误,它会返回第三个参数。
对于数组过滤器,lodash有_.find(),但我宁愿使用常规的filter()。但我仍然认为上面的方法_.get()在处理非常复杂的数据时非常有用。我在过去遇到过非常复杂的api,它很方便!
我希望它能对那些正在寻找操作标题所暗示的真正复杂数据的选项的人有用。
如果你愿意包含一个库,使用JSONPath将是最灵活的解决方案之一: https://github.com/s3u/JSONPath(节点和浏览器)
对于你的用例,json路径是:
$..items[1].name
so:
var secondName = jsonPath.eval(data, "$..items[1].name");