繁体   English   中英

如何从嵌套对象中获取所有具有值的键

[英]How to get all keys with values from nested objects

我正在寻找类似Object.keys的东西,但它适用于潜在的嵌套对象。 它也不应该包括具有对象/数组值的键(它应该只包括具有直接字符串/数字/布尔值的键)。

例一

输入

{
   "check_id":12345,
   "check_name":"Name of HTTP check",
   "check_type":"HTTP"
}

预计 output

[
  "check_id",
  "check_name",
  "check_type"
]

Object.keys适用于这样的平面案例,但不适用于嵌套案例:

例子二

输入

{
   "check_id":12345,
   "check_name":"Name of HTTP check",
   "check_type":"HTTP",
   "tags":[
     "example_tag"
   ],
   "check_params":{
      "basic_auth":false,
      "params":[
        "size"
      ],
      "encryption": {
        "enabled": true,
      }
   }
}

预计 output

[
  "check_id",
  "check_name",
  "check_type",
  "check_params.basic_auth",
  "check_params.encryption.enabled"
]

请注意,这不包括tagscheck_paramscheck_params.paramscheck_params.encryption因为这些值是数组/对象。

问题

有做这个的图书馆吗? 你将如何实现它,以便它可以与任何 object 一起工作,无论是大的还是嵌套的,还是小的?

你可以像这样使用 reduce:

 const keyify = (obj, prefix = '') => Object.keys(obj).reduce((res, el) => { if( Array.isArray(obj[el]) ) { return res; } else if( typeof obj[el] === 'object' && obj[el] !== null ) { return [...res, ...keyify(obj[el], prefix + el + '.')]; } return [...res, prefix + el]; }, []); const input = { "check_id":12345, "check_name":"Name of HTTP check", "check_type":"HTTP", "tags":[ "example_tag" ], "check_params":{ "basic_auth":false, "params":[ "size" ], "encryption": { "enabled": true, "testNull": null, } } }; const output = keyify(input); console.log(output);

Edit1:对于要包含数组的一般情况。

 const keyify = (obj, prefix = '') => Object.keys(obj).reduce((res, el) => { if( typeof obj[el] === 'object' && obj[el] !== null ) { return [...res, ...keyify(obj[el], prefix + el + '.')]; } return [...res, prefix + el]; }, []); const input = { "check_id":12345, "check_name":"Name of HTTP check", "check_type":"HTTP", "tags":[ "example_tag" ], "nested": [ { "foo": 0 }, { "bar": 1 } ], "check_params":{ "basic_auth":false, "params":[ "size" ], "encryption": { "enabled": true, "testNull": null, } } }; const output = keyify(input); console.log(output);

生成器可以快速解决此类问题 -

 function* deepKeys (t, pre = []) { if (Array.isArray(t)) return else if (Object(t) === t) for (const [k, v] of Object.entries(t)) yield* deepKeys(v, [...pre, k]) else yield pre.join(".") } const input = {check_id:12345,check_name:"Name of HTTP check",check_type:"HTTP",tags:["example_tag"],check_params:{basic_auth:false,params:["size"],encryption:{enabled:true,testNull:null,}}} console.log(Array.from(deepKeys(input)))

[ "check_id"
, "check_name"
, "check_type"
, "check_params.basic_auth"
, "check_params.encryption.enabled"
, "check_params.encryption.testNull"
]

或者一个热切地计算所有键的纯函数表达式 -

 const deepKeys = (t, pre = []) => Array.isArray(t) ? [] : Object(t) === t ? Object .entries(t) .flatMap(([k, v]) => deepKeys(v, [...pre, k])) : pre.join(".") const input = {check_id:12345,check_name:"Name of HTTP check",check_type:"HTTP",tags:["example_tag"],check_params:{basic_auth:false,params:["size"],encryption:{enabled:true,testNull:null,}}} console.log(deepKeys(input))

[ "check_id"
, "check_name"
, "check_type"
, "check_params.basic_auth"
, "check_params.encryption.enabled"
, "check_params.encryption.testNull"
]

您可以使用for...in并创建递归函数。

 var obj = {"check_id":12345,"check_name":"Name of HTTP check","check_type":"HTTP","tags":["example_tag"],"check_params":{"basic_auth":false,"params":["size",{"a":"b"}],"encryption":{"enabled":true}}} var keys = [] function getKeys(data, k = '') { for (var i in data) { var rest = k.length ? '.' + i : i if (typeof data[i] == 'object') { if (!Array.isArray(data[i])) { getKeys(data[i], k + rest) } } else keys.push(k + rest) } } getKeys(obj) console.log(keys)

您可以检查键并进行迭代,否则将路径推送到结果集。

 function getKeys(object) { function iter(o, p) { if (Array.isArray(o)) { return; } if (o && typeof o === 'object') { var keys = Object.keys(o); if (keys.length) { keys.forEach(function (k) { iter(o[k], p.concat(k)); }); } return; } result.push(p.join('.')); } var result = []; iter(object, []); return result; } var object = { check_id: 12345, check_name: "Name of HTTP check", check_type: "HTTP", tags: ["example_tag"], check_params: { basic_auth: false, params: ["size"], encryption: { enabled: true } } }; console.log(getKeys(object));
 .as-console-wrapper { max-height: 100% !important; top: 0; }

 var json = { id: '1234', test: 'terst', user : { name: '', details: { address: { add2: { prim: "", sec: "" }, add1: '', } } }, salary: { cur: 1234, net: 89797 }, age: 12 } let arr = []; let initialObj = {}; function getKeys(obj, parentK=''){ initialObj = arr.length === 0 ? obj: initialObj; const entries = Object.entries(obj); for(let i=0; i<entries.length; i++) { const key = entries[i][0]; const val = entries[i][1]; const isRootElement = initialObj.hasOwnProperty(key); parentK = isRootElement ? key: parentK+'.'+key; arr.push(parentK) if(typeof val === 'object' && val!==null && !Array.isArray(val)){ getKeys(val, parentK); } } } getKeys(json) console.log('arr final---', arr);

进一步增强上述建议以返回包括数组在内的所有键。

 const keyify = (obj, prefix = '') => 
  Object.keys(obj).reduce((res, el) => {
    if( Array.isArray(obj[el]) ) {
      return [...res,`${el}: ${obj[el].toString()}`];
    } else if( typeof obj[el] === 'object' && obj[el] !== null ) {
      return [...res,...keyify(obj[el],`${prefix}${el}.`)];
    }
    return [...res,`${prefix}${el}: ${obj[el]}`];
  }, []);
  
const input = {
   "check_id":12345,
   "check_name":"Name of HTTP check",
   "check_type":"HTTP",
   "tags":[
     "example_tag"
   ],
   "check_params":{
      "basic_auth":false,
      "params":[
        "size"
      ],
      "encryption": {
        "enabled": true,
        "testNull": null,
      }
   }
};

const output = keyify(input);
console.log(output);

预计 output:

[
  'check_id: 12345',
  'check_name: Name of HTTP check',
  'check_type: HTTP',
  'tags: example_tag',
  'check_params.basic_auth: false',
  'params: size',
  'check_params.encryption.enabled: true',
  'check_params.encryption.testNull: null'
]

这是你的意思吗?

http://jsfiddle.net/robbiemilejczak/hfe12brb/1/

我不能用 vanilla JS 做到这一点,这是一个依赖 lodash 的非常hacky 的解决方案。 基本上利用 lodashs _.forIn_.isArray函数来迭代对象。 此外,这只会深入 1 层,因此嵌套对象内部的对象将被忽略。 不过,它确实会产生您预期的输出,所以我认为这是一个不错的起点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM