Javascript 在大对象中查找嵌套键
Javascript find nested key in a large object
我正在尝试获取嵌套在这个 JSON 对象中的 eth0
的值
"addresses": {
"eth0": [
"10.0.3.188"
]
},
我使用 underscore.js 来简化流程
var _ = require('underscore')._;
var jsonData = {
"plays": [{
"play": {
"id": "d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",
"name": "lxc"
},
"tasks": [{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc copy base \"bar69\"",
"delta": "0:00:01.417533",
"end": "2017-01-10 18:01:28.692981",
"invocation": {
"module_args": {
"_raw_params": "lxc copy base \"bar69\"",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:27.275448",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "297bf7b7-9ee7-4517-8763-bc3b15baa6e2",
"name": "clone from base"
}
},
{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc config set \"bar69\" security.privileged true",
"delta": "0:00:00.053403",
"end": "2017-01-10 18:01:32.270750",
"invocation": {
"module_args": {
"_raw_params": "lxc config set \"bar69\" security.privileged true",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:32.217347",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "bc63ad6f-1808-48b8-a1de-729153d2b0c5",
"name": "Promote to privileged ct"
}
},
{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"actions": [
"start"
],
"addresses": {
"eth0": [
"10.0.3.188"
]
},
"changed": true,
"invocation": {
"module_args": {
"architecture": null,
"cert_file": "/root/.config/lxc/client.crt",
"config": null,
"description": null,
"devices": null,
"ephemeral": null,
"force_stop": false,
"key_file": "/root/.config/lxc/client.key",
"name": "bar69",
"profiles": null,
"source": null,
"state": "started",
"timeout": 30,
"trust_password": null,
"url": "unix:/var/lib/lxd/unix.socket",
"wait_for_ipv4_addresses": true
},
"module_name": "lxd_container"
},
"log_verbosity": 0,
"old_state": "stopped"
}
},
"task": {
"id": "466c0da9-6cbf-4196-aea9-109218c3ed5f",
"name": "Start CT"
}
},
{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"invocation": {
"module_args": {
"msg": [
"10.0.3.188"
]
},
"module_name": "debug"
},
"msg": [
"10.0.3.188"
]
}
},
"task": {
"id": "978c490e-59c3-41d2-818d-ab4b557ad803",
"name": ""
}
}
]
}],
"stats": {
"lxc.server.com": {
"changed": 3,
"failures": 0,
"ok": 4,
"skipped": 0,
"unreachable": 0
}
}
}
这是我迄今为止尝试过的方法,但没有成功!
console.log(_.findKey(_.values(jsonData.tasks)));
非常感谢您的帮助
您可以使用此代码循环对象属性。
for (key in jsonData){
if(key == "eth0" ){
console.log(jsonData[key].toString())
}
}
你可以不用下划线来做到这一点。您可以采用的一种方法是采用给定的 属性 字符串和一个任务,根据分隔符拆分 属性 (您不能使用 '.'
因为您有 'lxc.server.com'
之类的点状属性),并递归地检查对象,直到找到(或找不到)值。
注意:下面的解决方案假设你想传递一个分隔的 属性 字符串,但你可以直接传递一个 props 数组而不用包装辅助函数。
尾尾递归求解
var jsonData={plays:[{play:{id:"d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",name:"lxc"},tasks:[{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc copy base "bar69"',delta:"0:00:01.417533",end:"2017-01-10 18:01:28.692981",invocation:{module_args:{_raw_params:'lxc copy base "bar69"',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:27.275448",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"297bf7b7-9ee7-4517-8763-bc3b15baa6e2",name:"clone from base"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc config set "bar69" security.privileged true',delta:"0:00:00.053403",end:"2017-01-10 18:01:32.270750",invocation:{module_args:{_raw_params:'lxc config set "bar69" security.privileged true',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:32.217347",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"bc63ad6f-1808-48b8-a1de-729153d2b0c5",name:"Promote to privileged ct"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,actions:["start"],addresses:{eth0:["10.0.3.188"]},changed:!0,invocation:{module_args:{architecture:null,cert_file:"/root/.config/lxc/client.crt",config:null,description:null,devices:null,ephemeral:null,force_stop:!1,key_file:"/root/.config/lxc/client.key",name:"bar69",profiles:null,source:null,state:"started",timeout:30,trust_password:null,url:"unix:/var/lib/lxd/unix.socket",wait_for_ipv4_addresses:!0},module_name:"lxd_container"},log_verbosity:0,old_state:"stopped"}},task:{id:"466c0da9-6cbf-4196-aea9-109218c3ed5f",name:"Start CT"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_verbose_always:!0,changed:!1,invocation:{module_args:{msg:["10.0.3.188"]},module_name:"debug"},msg:["10.0.3.188"]}},task:{id:"978c490e-59c3-41d2-818d-ab4b557ad803",name:""}}]}],stats:{"lxc.server.com":{changed:3,failures:0,ok:4,skipped:0,unreachable:0}}};
function getNestedPropHelper(obj, [first, ...rest]) {
// base case
if (typeof obj !== 'object' || !obj) return undefined;
return rest.length === 0 // if we only have one property
? obj[first] // return the value
: getNestedPropHelper(obj[first], rest); // otherwise recursively return the rest
}
function getNestedProp(obj, prop, delim = '|') {
return getNestedPropHelper(obj, prop.split(delim));
}
// extract the tasks
const tasks = jsonData.plays.reduce((arr, play) => arr.concat(play.tasks), []);
// get the eth0 property for each task
const props = tasks.map(task =>
getNestedProp(task, 'hosts|lxc.server.com|addresses|eth0')
);
// log eth0 properties for each task (only the third one actually has the value)
console.log(props);
您也可以迭代地执行此操作,这通常会更快(尽管在支持尾调用的环境中速度并不快):
迭代求解
var jsonData={plays:[{play:{id:"d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",name:"lxc"},tasks:[{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc copy base "bar69"',delta:"0:00:01.417533",end:"2017-01-10 18:01:28.692981",invocation:{module_args:{_raw_params:'lxc copy base "bar69"',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:27.275448",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"297bf7b7-9ee7-4517-8763-bc3b15baa6e2",name:"clone from base"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc config set "bar69" security.privileged true',delta:"0:00:00.053403",end:"2017-01-10 18:01:32.270750",invocation:{module_args:{_raw_params:'lxc config set "bar69" security.privileged true',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:32.217347",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"bc63ad6f-1808-48b8-a1de-729153d2b0c5",name:"Promote to privileged ct"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,actions:["start"],addresses:{eth0:["10.0.3.188"]},changed:!0,invocation:{module_args:{architecture:null,cert_file:"/root/.config/lxc/client.crt",config:null,description:null,devices:null,ephemeral:null,force_stop:!1,key_file:"/root/.config/lxc/client.key",name:"bar69",profiles:null,source:null,state:"started",timeout:30,trust_password:null,url:"unix:/var/lib/lxd/unix.socket",wait_for_ipv4_addresses:!0},module_name:"lxd_container"},log_verbosity:0,old_state:"stopped"}},task:{id:"466c0da9-6cbf-4196-aea9-109218c3ed5f",name:"Start CT"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_verbose_always:!0,changed:!1,invocation:{module_args:{msg:["10.0.3.188"]},module_name:"debug"},msg:["10.0.3.188"]}},task:{id:"978c490e-59c3-41d2-818d-ab4b557ad803",name:""}}]}],stats:{"lxc.server.com":{changed:3,failures:0,ok:4,skipped:0,unreachable:0}}};
function getNestedPropHelper(obj, props) {
const isObject = (obj) => typeof obj === 'object' && obj;
if (!isObject(obj)) return undefined;
// keep extracting the properties
for (const prop of props) {
obj = obj[prop];
// of we come across a non-object property before we're done, the property path is invalid
if (!isObject(obj)) return undefined;
}
// if we reached this point, we found the value
return obj;
}
function getNestedProp(obj, prop, delim = '|') {
return getNestedPropHelper(obj, prop.split(delim));
}
// extract the tasks
const tasks = jsonData.plays.reduce((arr, play) => arr.concat(play.tasks), []);
// get the eth0 property for each task
const props = tasks.map(task =>
getNestedProp(task, 'hosts|lxc.server.com|addresses|eth0')
);
// log eth0 properties for each task (only the third one actually has the value)
console.log(props);
Curried 递归解决方案 迭代解决方案可以采用相同的方法
您还可以 curry 该函数,这样您就可以为某些 属性 路径构建 getter。
var jsonData={plays:[{play:{id:"d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",name:"lxc"},tasks:[{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc copy base "bar69"',delta:"0:00:01.417533",end:"2017-01-10 18:01:28.692981",invocation:{module_args:{_raw_params:'lxc copy base "bar69"',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:27.275448",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"297bf7b7-9ee7-4517-8763-bc3b15baa6e2",name:"clone from base"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc config set "bar69" security.privileged true',delta:"0:00:00.053403",end:"2017-01-10 18:01:32.270750",invocation:{module_args:{_raw_params:'lxc config set "bar69" security.privileged true',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:32.217347",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"bc63ad6f-1808-48b8-a1de-729153d2b0c5",name:"Promote to privileged ct"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,actions:["start"],addresses:{eth0:["10.0.3.188"]},changed:!0,invocation:{module_args:{architecture:null,cert_file:"/root/.config/lxc/client.crt",config:null,description:null,devices:null,ephemeral:null,force_stop:!1,key_file:"/root/.config/lxc/client.key",name:"bar69",profiles:null,source:null,state:"started",timeout:30,trust_password:null,url:"unix:/var/lib/lxd/unix.socket",wait_for_ipv4_addresses:!0},module_name:"lxd_container"},log_verbosity:0,old_state:"stopped"}},task:{id:"466c0da9-6cbf-4196-aea9-109218c3ed5f",name:"Start CT"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_verbose_always:!0,changed:!1,invocation:{module_args:{msg:["10.0.3.188"]},module_name:"debug"},msg:["10.0.3.188"]}},task:{id:"978c490e-59c3-41d2-818d-ab4b557ad803",name:""}}]}],stats:{"lxc.server.com":{changed:3,failures:0,ok:4,skipped:0,unreachable:0}}};
function getNestedPropHelper(obj, [first, ...rest]) {
// base case
if (typeof obj !== 'object' || !obj) return undefined;
return rest.length === 0 // if we only have one property
? obj[first] // return the value
: getNestedPropHelper(obj[first], rest); // otherwise recursively return the rest
}
function getNestedProp(prop, delim = '|') {
const props = prop.split(delim);
return function(obj) {
return getNestedPropHelper(obj, props);
}
}
// now you have a getter that will extract eth0 for any task
const getEth0 = getNestedProp('hosts|lxc.server.com|addresses|eth0');
// extract the tasks
const tasks = jsonData.plays.reduce((arr, play) => arr.concat(play.tasks), []);
// extract eth0 from each task
const props = tasks.map(getEth0);
// log eth0 properties for each task (only the third one actually has the value)
console.log(props);
如果您想直接访问它,请尝试以下操作:
jsonData.plays[0].tasks[2].hosts["lxc.server.com"].addresses.eth0[0]
编辑:这已经过测试。具有任务 [3] 的 post 不正确。
您可以使用一些函数,例如 _.pluck() to get the objects at key host, _.property() to see if each host object has a key addresses, .map() to get a mapping of the values, ._filter() 来查看是否从映射返回值等:
var hosts = _.pluck(jsonData.plays[0].tasks, 'hosts');
var mapping = _.map(hosts, function(host) {
var keys = _.keys(host);
if (_.size(keys)) {
var nestedHost = host[_.first(keys)];
if (_.property('addresses')(nestedHost)) {
if (_.property('eth0')(nestedHost.addresses)) {
return nestedHost.addresses.eth0[0];
}
}
}
});
console.log(_.filter(mapping));
在 this plunker 中查看实际操作,以及下面的示例:
var jsonData = {
"plays": [{
"play": {
"id": "d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",
"name": "lxc"
},
"tasks": [{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc copy base \"bar69\"",
"delta": "0:00:01.417533",
"end": "2017-01-10 18:01:28.692981",
"invocation": {
"module_args": {
"_raw_params": "lxc copy base \"bar69\"",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:27.275448",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "297bf7b7-9ee7-4517-8763-bc3b15baa6e2",
"name": "clone from base"
}
}, {
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc config set \"bar69\" security.privileged true",
"delta": "0:00:00.053403",
"end": "2017-01-10 18:01:32.270750",
"invocation": {
"module_args": {
"_raw_params": "lxc config set \"bar69\" security.privileged true",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:32.217347",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "bc63ad6f-1808-48b8-a1de-729153d2b0c5",
"name": "Promote to privileged ct"
}
}, {
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"actions": [
"start"
],
"addresses": {
"eth0": [
"10.0.3.188"
]
},
"changed": true,
"invocation": {
"module_args": {
"architecture": null,
"cert_file": "/root/.config/lxc/client.crt",
"config": null,
"description": null,
"devices": null,
"ephemeral": null,
"force_stop": false,
"key_file": "/root/.config/lxc/client.key",
"name": "bar69",
"profiles": null,
"source": null,
"state": "started",
"timeout": 30,
"trust_password": null,
"url": "unix:/var/lib/lxd/unix.socket",
"wait_for_ipv4_addresses": true
},
"module_name": "lxd_container"
},
"log_verbosity": 0,
"old_state": "stopped"
}
},
"task": {
"id": "466c0da9-6cbf-4196-aea9-109218c3ed5f",
"name": "Start CT"
}
}, {
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"invocation": {
"module_args": {
"msg": [
"10.0.3.188"
]
},
"module_name": "debug"
},
"msg": [
"10.0.3.188"
]
}
},
"task": {
"id": "978c490e-59c3-41d2-818d-ab4b557ad803",
"name": ""
}
}]
}],
"stats": {
"lxc.server.com": {
"changed": 3,
"failures": 0,
"ok": 4,
"skipped": 0,
"unreachable": 0
}
}
};
document.addEventListener('DOMContentLoaded', function() {
var hosts = _.pluck(jsonData.plays[0].tasks, 'hosts');
var mapping = _.map(hosts, function(host) {
var keys = _.keys(host);
if (_.size(keys)) {
var nestedHost = host[_.first(keys)];
if (_.property('addresses')(nestedHost)) {
if (_.property('eth0')(nestedHost.addresses)) {
return nestedHost.addresses.eth0[0];
}
}
}
});
document.getElementById('console').innerHTML = _.filter(mapping);
});
<script data-require="underscore.js@*" data-semver="1.8.3" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
Address(es):
<div id="console"></div>
我们使用 object-scan 进行许多数据处理任务。一旦您全神贯注,它就会强大而快速。以下是您可以如何解决您的问题
// const objectScan = require('object-scan');
const find = (input) => objectScan(['**.addresses.eth0[0]'], {
abort: true,
rtn: 'value'
})(input);
const jsonData = { plays: [{ play: { id: 'd10aae34-6713-4e14-8ad5-fa2fbf6aa2b5', name: 'lxc' }, tasks: [{ hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_parsed: true, changed: true, cmd: 'lxc copy base "bar69"', delta: '0:00:01.417533', end: '2017-01-10 18:01:28.692981', invocation: { module_args: { _raw_params: 'lxc copy base "bar69"', _uses_shell: true, chdir: null, creates: null, executable: null, removes: null, warn: true }, module_name: 'command' }, rc: 0, start: '2017-01-10 18:01:27.275448', stderr: '', stdout: '', stdout_lines: [], warnings: [] } }, task: { id: '297bf7b7-9ee7-4517-8763-bc3b15baa6e2', name: 'clone from base' } }, { hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_parsed: true, changed: true, cmd: 'lxc config set "bar69" security.privileged true', delta: '0:00:00.053403', end: '2017-01-10 18:01:32.270750', invocation: { module_args: { _raw_params: 'lxc config set "bar69" security.privileged true', _uses_shell: true, chdir: null, creates: null, executable: null, removes: null, warn: true }, module_name: 'command' }, rc: 0, start: '2017-01-10 18:01:32.217347', stderr: '', stdout: '', stdout_lines: [], warnings: [] } }, task: { id: 'bc63ad6f-1808-48b8-a1de-729153d2b0c5', name: 'Promote to privileged ct' } }, { hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_parsed: true, actions: ['start'], addresses: { eth0: ['10.0.3.188'] }, changed: true, invocation: { module_args: { architecture: null, cert_file: '/root/.config/lxc/client.crt', config: null, description: null, devices: null, ephemeral: null, force_stop: false, key_file: '/root/.config/lxc/client.key', name: 'bar69', profiles: null, source: null, state: 'started', timeout: 30, trust_password: null, url: 'unix:/var/lib/lxd/unix.socket', wait_for_ipv4_addresses: true }, module_name: 'lxd_container' }, log_verbosity: 0, old_state: 'stopped' } }, task: { id: '466c0da9-6cbf-4196-aea9-109218c3ed5f', name: 'Start CT' } }, { hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_verbose_always: true, changed: false, invocation: { module_args: { msg: ['10.0.3.188'] }, module_name: 'debug' }, msg: ['10.0.3.188'] } }, task: { id: '978c490e-59c3-41d2-818d-ab4b557ad803', name: '' } }] }], stats: { 'lxc.server.com': { changed: 3, failures: 0, ok: 4, skipped: 0, unreachable: 0 } } };
console.log(find(jsonData));
// => 10.0.3.188
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>
免责声明:我是object-scan
的作者
我正在尝试获取嵌套在这个 JSON 对象中的 eth0
的值
"addresses": {
"eth0": [
"10.0.3.188"
]
},
我使用 underscore.js 来简化流程
var _ = require('underscore')._;
var jsonData = {
"plays": [{
"play": {
"id": "d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",
"name": "lxc"
},
"tasks": [{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc copy base \"bar69\"",
"delta": "0:00:01.417533",
"end": "2017-01-10 18:01:28.692981",
"invocation": {
"module_args": {
"_raw_params": "lxc copy base \"bar69\"",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:27.275448",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "297bf7b7-9ee7-4517-8763-bc3b15baa6e2",
"name": "clone from base"
}
},
{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc config set \"bar69\" security.privileged true",
"delta": "0:00:00.053403",
"end": "2017-01-10 18:01:32.270750",
"invocation": {
"module_args": {
"_raw_params": "lxc config set \"bar69\" security.privileged true",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:32.217347",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "bc63ad6f-1808-48b8-a1de-729153d2b0c5",
"name": "Promote to privileged ct"
}
},
{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"actions": [
"start"
],
"addresses": {
"eth0": [
"10.0.3.188"
]
},
"changed": true,
"invocation": {
"module_args": {
"architecture": null,
"cert_file": "/root/.config/lxc/client.crt",
"config": null,
"description": null,
"devices": null,
"ephemeral": null,
"force_stop": false,
"key_file": "/root/.config/lxc/client.key",
"name": "bar69",
"profiles": null,
"source": null,
"state": "started",
"timeout": 30,
"trust_password": null,
"url": "unix:/var/lib/lxd/unix.socket",
"wait_for_ipv4_addresses": true
},
"module_name": "lxd_container"
},
"log_verbosity": 0,
"old_state": "stopped"
}
},
"task": {
"id": "466c0da9-6cbf-4196-aea9-109218c3ed5f",
"name": "Start CT"
}
},
{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"invocation": {
"module_args": {
"msg": [
"10.0.3.188"
]
},
"module_name": "debug"
},
"msg": [
"10.0.3.188"
]
}
},
"task": {
"id": "978c490e-59c3-41d2-818d-ab4b557ad803",
"name": ""
}
}
]
}],
"stats": {
"lxc.server.com": {
"changed": 3,
"failures": 0,
"ok": 4,
"skipped": 0,
"unreachable": 0
}
}
}
这是我迄今为止尝试过的方法,但没有成功!
console.log(_.findKey(_.values(jsonData.tasks)));
非常感谢您的帮助
您可以使用此代码循环对象属性。
for (key in jsonData){
if(key == "eth0" ){
console.log(jsonData[key].toString())
}
}
你可以不用下划线来做到这一点。您可以采用的一种方法是采用给定的 属性 字符串和一个任务,根据分隔符拆分 属性 (您不能使用 '.'
因为您有 'lxc.server.com'
之类的点状属性),并递归地检查对象,直到找到(或找不到)值。
注意:下面的解决方案假设你想传递一个分隔的 属性 字符串,但你可以直接传递一个 props 数组而不用包装辅助函数。
尾尾递归求解
var jsonData={plays:[{play:{id:"d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",name:"lxc"},tasks:[{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc copy base "bar69"',delta:"0:00:01.417533",end:"2017-01-10 18:01:28.692981",invocation:{module_args:{_raw_params:'lxc copy base "bar69"',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:27.275448",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"297bf7b7-9ee7-4517-8763-bc3b15baa6e2",name:"clone from base"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc config set "bar69" security.privileged true',delta:"0:00:00.053403",end:"2017-01-10 18:01:32.270750",invocation:{module_args:{_raw_params:'lxc config set "bar69" security.privileged true',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:32.217347",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"bc63ad6f-1808-48b8-a1de-729153d2b0c5",name:"Promote to privileged ct"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,actions:["start"],addresses:{eth0:["10.0.3.188"]},changed:!0,invocation:{module_args:{architecture:null,cert_file:"/root/.config/lxc/client.crt",config:null,description:null,devices:null,ephemeral:null,force_stop:!1,key_file:"/root/.config/lxc/client.key",name:"bar69",profiles:null,source:null,state:"started",timeout:30,trust_password:null,url:"unix:/var/lib/lxd/unix.socket",wait_for_ipv4_addresses:!0},module_name:"lxd_container"},log_verbosity:0,old_state:"stopped"}},task:{id:"466c0da9-6cbf-4196-aea9-109218c3ed5f",name:"Start CT"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_verbose_always:!0,changed:!1,invocation:{module_args:{msg:["10.0.3.188"]},module_name:"debug"},msg:["10.0.3.188"]}},task:{id:"978c490e-59c3-41d2-818d-ab4b557ad803",name:""}}]}],stats:{"lxc.server.com":{changed:3,failures:0,ok:4,skipped:0,unreachable:0}}};
function getNestedPropHelper(obj, [first, ...rest]) {
// base case
if (typeof obj !== 'object' || !obj) return undefined;
return rest.length === 0 // if we only have one property
? obj[first] // return the value
: getNestedPropHelper(obj[first], rest); // otherwise recursively return the rest
}
function getNestedProp(obj, prop, delim = '|') {
return getNestedPropHelper(obj, prop.split(delim));
}
// extract the tasks
const tasks = jsonData.plays.reduce((arr, play) => arr.concat(play.tasks), []);
// get the eth0 property for each task
const props = tasks.map(task =>
getNestedProp(task, 'hosts|lxc.server.com|addresses|eth0')
);
// log eth0 properties for each task (only the third one actually has the value)
console.log(props);
您也可以迭代地执行此操作,这通常会更快(尽管在支持尾调用的环境中速度并不快):
迭代求解
var jsonData={plays:[{play:{id:"d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",name:"lxc"},tasks:[{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc copy base "bar69"',delta:"0:00:01.417533",end:"2017-01-10 18:01:28.692981",invocation:{module_args:{_raw_params:'lxc copy base "bar69"',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:27.275448",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"297bf7b7-9ee7-4517-8763-bc3b15baa6e2",name:"clone from base"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc config set "bar69" security.privileged true',delta:"0:00:00.053403",end:"2017-01-10 18:01:32.270750",invocation:{module_args:{_raw_params:'lxc config set "bar69" security.privileged true',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:32.217347",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"bc63ad6f-1808-48b8-a1de-729153d2b0c5",name:"Promote to privileged ct"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,actions:["start"],addresses:{eth0:["10.0.3.188"]},changed:!0,invocation:{module_args:{architecture:null,cert_file:"/root/.config/lxc/client.crt",config:null,description:null,devices:null,ephemeral:null,force_stop:!1,key_file:"/root/.config/lxc/client.key",name:"bar69",profiles:null,source:null,state:"started",timeout:30,trust_password:null,url:"unix:/var/lib/lxd/unix.socket",wait_for_ipv4_addresses:!0},module_name:"lxd_container"},log_verbosity:0,old_state:"stopped"}},task:{id:"466c0da9-6cbf-4196-aea9-109218c3ed5f",name:"Start CT"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_verbose_always:!0,changed:!1,invocation:{module_args:{msg:["10.0.3.188"]},module_name:"debug"},msg:["10.0.3.188"]}},task:{id:"978c490e-59c3-41d2-818d-ab4b557ad803",name:""}}]}],stats:{"lxc.server.com":{changed:3,failures:0,ok:4,skipped:0,unreachable:0}}};
function getNestedPropHelper(obj, props) {
const isObject = (obj) => typeof obj === 'object' && obj;
if (!isObject(obj)) return undefined;
// keep extracting the properties
for (const prop of props) {
obj = obj[prop];
// of we come across a non-object property before we're done, the property path is invalid
if (!isObject(obj)) return undefined;
}
// if we reached this point, we found the value
return obj;
}
function getNestedProp(obj, prop, delim = '|') {
return getNestedPropHelper(obj, prop.split(delim));
}
// extract the tasks
const tasks = jsonData.plays.reduce((arr, play) => arr.concat(play.tasks), []);
// get the eth0 property for each task
const props = tasks.map(task =>
getNestedProp(task, 'hosts|lxc.server.com|addresses|eth0')
);
// log eth0 properties for each task (only the third one actually has the value)
console.log(props);
Curried 递归解决方案 迭代解决方案可以采用相同的方法
您还可以 curry 该函数,这样您就可以为某些 属性 路径构建 getter。
var jsonData={plays:[{play:{id:"d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",name:"lxc"},tasks:[{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc copy base "bar69"',delta:"0:00:01.417533",end:"2017-01-10 18:01:28.692981",invocation:{module_args:{_raw_params:'lxc copy base "bar69"',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:27.275448",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"297bf7b7-9ee7-4517-8763-bc3b15baa6e2",name:"clone from base"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,changed:!0,cmd:'lxc config set "bar69" security.privileged true',delta:"0:00:00.053403",end:"2017-01-10 18:01:32.270750",invocation:{module_args:{_raw_params:'lxc config set "bar69" security.privileged true',_uses_shell:!0,chdir:null,creates:null,executable:null,removes:null,warn:!0},module_name:"command"},rc:0,start:"2017-01-10 18:01:32.217347",stderr:"",stdout:"",stdout_lines:[],warnings:[]}},task:{id:"bc63ad6f-1808-48b8-a1de-729153d2b0c5",name:"Promote to privileged ct"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_parsed:!0,actions:["start"],addresses:{eth0:["10.0.3.188"]},changed:!0,invocation:{module_args:{architecture:null,cert_file:"/root/.config/lxc/client.crt",config:null,description:null,devices:null,ephemeral:null,force_stop:!1,key_file:"/root/.config/lxc/client.key",name:"bar69",profiles:null,source:null,state:"started",timeout:30,trust_password:null,url:"unix:/var/lib/lxd/unix.socket",wait_for_ipv4_addresses:!0},module_name:"lxd_container"},log_verbosity:0,old_state:"stopped"}},task:{id:"466c0da9-6cbf-4196-aea9-109218c3ed5f",name:"Start CT"}},{hosts:{"lxc.server.com":{_ansible_no_log:!1,_ansible_verbose_always:!0,changed:!1,invocation:{module_args:{msg:["10.0.3.188"]},module_name:"debug"},msg:["10.0.3.188"]}},task:{id:"978c490e-59c3-41d2-818d-ab4b557ad803",name:""}}]}],stats:{"lxc.server.com":{changed:3,failures:0,ok:4,skipped:0,unreachable:0}}};
function getNestedPropHelper(obj, [first, ...rest]) {
// base case
if (typeof obj !== 'object' || !obj) return undefined;
return rest.length === 0 // if we only have one property
? obj[first] // return the value
: getNestedPropHelper(obj[first], rest); // otherwise recursively return the rest
}
function getNestedProp(prop, delim = '|') {
const props = prop.split(delim);
return function(obj) {
return getNestedPropHelper(obj, props);
}
}
// now you have a getter that will extract eth0 for any task
const getEth0 = getNestedProp('hosts|lxc.server.com|addresses|eth0');
// extract the tasks
const tasks = jsonData.plays.reduce((arr, play) => arr.concat(play.tasks), []);
// extract eth0 from each task
const props = tasks.map(getEth0);
// log eth0 properties for each task (only the third one actually has the value)
console.log(props);
如果您想直接访问它,请尝试以下操作:
jsonData.plays[0].tasks[2].hosts["lxc.server.com"].addresses.eth0[0]
编辑:这已经过测试。具有任务 [3] 的 post 不正确。
您可以使用一些函数,例如 _.pluck() to get the objects at key host, _.property() to see if each host object has a key addresses, .map() to get a mapping of the values, ._filter() 来查看是否从映射返回值等:
var hosts = _.pluck(jsonData.plays[0].tasks, 'hosts');
var mapping = _.map(hosts, function(host) {
var keys = _.keys(host);
if (_.size(keys)) {
var nestedHost = host[_.first(keys)];
if (_.property('addresses')(nestedHost)) {
if (_.property('eth0')(nestedHost.addresses)) {
return nestedHost.addresses.eth0[0];
}
}
}
});
console.log(_.filter(mapping));
在 this plunker 中查看实际操作,以及下面的示例:
var jsonData = {
"plays": [{
"play": {
"id": "d10aae34-6713-4e14-8ad5-fa2fbf6aa2b5",
"name": "lxc"
},
"tasks": [{
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc copy base \"bar69\"",
"delta": "0:00:01.417533",
"end": "2017-01-10 18:01:28.692981",
"invocation": {
"module_args": {
"_raw_params": "lxc copy base \"bar69\"",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:27.275448",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "297bf7b7-9ee7-4517-8763-bc3b15baa6e2",
"name": "clone from base"
}
}, {
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": true,
"cmd": "lxc config set \"bar69\" security.privileged true",
"delta": "0:00:00.053403",
"end": "2017-01-10 18:01:32.270750",
"invocation": {
"module_args": {
"_raw_params": "lxc config set \"bar69\" security.privileged true",
"_uses_shell": true,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"warn": true
},
"module_name": "command"
},
"rc": 0,
"start": "2017-01-10 18:01:32.217347",
"stderr": "",
"stdout": "",
"stdout_lines": [],
"warnings": []
}
},
"task": {
"id": "bc63ad6f-1808-48b8-a1de-729153d2b0c5",
"name": "Promote to privileged ct"
}
}, {
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_parsed": true,
"actions": [
"start"
],
"addresses": {
"eth0": [
"10.0.3.188"
]
},
"changed": true,
"invocation": {
"module_args": {
"architecture": null,
"cert_file": "/root/.config/lxc/client.crt",
"config": null,
"description": null,
"devices": null,
"ephemeral": null,
"force_stop": false,
"key_file": "/root/.config/lxc/client.key",
"name": "bar69",
"profiles": null,
"source": null,
"state": "started",
"timeout": 30,
"trust_password": null,
"url": "unix:/var/lib/lxd/unix.socket",
"wait_for_ipv4_addresses": true
},
"module_name": "lxd_container"
},
"log_verbosity": 0,
"old_state": "stopped"
}
},
"task": {
"id": "466c0da9-6cbf-4196-aea9-109218c3ed5f",
"name": "Start CT"
}
}, {
"hosts": {
"lxc.server.com": {
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"invocation": {
"module_args": {
"msg": [
"10.0.3.188"
]
},
"module_name": "debug"
},
"msg": [
"10.0.3.188"
]
}
},
"task": {
"id": "978c490e-59c3-41d2-818d-ab4b557ad803",
"name": ""
}
}]
}],
"stats": {
"lxc.server.com": {
"changed": 3,
"failures": 0,
"ok": 4,
"skipped": 0,
"unreachable": 0
}
}
};
document.addEventListener('DOMContentLoaded', function() {
var hosts = _.pluck(jsonData.plays[0].tasks, 'hosts');
var mapping = _.map(hosts, function(host) {
var keys = _.keys(host);
if (_.size(keys)) {
var nestedHost = host[_.first(keys)];
if (_.property('addresses')(nestedHost)) {
if (_.property('eth0')(nestedHost.addresses)) {
return nestedHost.addresses.eth0[0];
}
}
}
});
document.getElementById('console').innerHTML = _.filter(mapping);
});
<script data-require="underscore.js@*" data-semver="1.8.3" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
Address(es):
<div id="console"></div>
我们使用 object-scan 进行许多数据处理任务。一旦您全神贯注,它就会强大而快速。以下是您可以如何解决您的问题
// const objectScan = require('object-scan');
const find = (input) => objectScan(['**.addresses.eth0[0]'], {
abort: true,
rtn: 'value'
})(input);
const jsonData = { plays: [{ play: { id: 'd10aae34-6713-4e14-8ad5-fa2fbf6aa2b5', name: 'lxc' }, tasks: [{ hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_parsed: true, changed: true, cmd: 'lxc copy base "bar69"', delta: '0:00:01.417533', end: '2017-01-10 18:01:28.692981', invocation: { module_args: { _raw_params: 'lxc copy base "bar69"', _uses_shell: true, chdir: null, creates: null, executable: null, removes: null, warn: true }, module_name: 'command' }, rc: 0, start: '2017-01-10 18:01:27.275448', stderr: '', stdout: '', stdout_lines: [], warnings: [] } }, task: { id: '297bf7b7-9ee7-4517-8763-bc3b15baa6e2', name: 'clone from base' } }, { hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_parsed: true, changed: true, cmd: 'lxc config set "bar69" security.privileged true', delta: '0:00:00.053403', end: '2017-01-10 18:01:32.270750', invocation: { module_args: { _raw_params: 'lxc config set "bar69" security.privileged true', _uses_shell: true, chdir: null, creates: null, executable: null, removes: null, warn: true }, module_name: 'command' }, rc: 0, start: '2017-01-10 18:01:32.217347', stderr: '', stdout: '', stdout_lines: [], warnings: [] } }, task: { id: 'bc63ad6f-1808-48b8-a1de-729153d2b0c5', name: 'Promote to privileged ct' } }, { hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_parsed: true, actions: ['start'], addresses: { eth0: ['10.0.3.188'] }, changed: true, invocation: { module_args: { architecture: null, cert_file: '/root/.config/lxc/client.crt', config: null, description: null, devices: null, ephemeral: null, force_stop: false, key_file: '/root/.config/lxc/client.key', name: 'bar69', profiles: null, source: null, state: 'started', timeout: 30, trust_password: null, url: 'unix:/var/lib/lxd/unix.socket', wait_for_ipv4_addresses: true }, module_name: 'lxd_container' }, log_verbosity: 0, old_state: 'stopped' } }, task: { id: '466c0da9-6cbf-4196-aea9-109218c3ed5f', name: 'Start CT' } }, { hosts: { 'lxc.server.com': { _ansible_no_log: false, _ansible_verbose_always: true, changed: false, invocation: { module_args: { msg: ['10.0.3.188'] }, module_name: 'debug' }, msg: ['10.0.3.188'] } }, task: { id: '978c490e-59c3-41d2-818d-ab4b557ad803', name: '' } }] }], stats: { 'lxc.server.com': { changed: 3, failures: 0, ok: 4, skipped: 0, unreachable: 0 } } };
console.log(find(jsonData));
// => 10.0.3.188
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>
免责声明:我是object-scan
的作者