【问题标题】:Access elements inside json object without knowing names在不知道名称的情况下访问 json 对象内的元素
【发布时间】:2016-07-02 01:22:34
【问题描述】:

我在 node.js 中有以下 json 对象。

x={
    '40': {
        length: '2',
        data: ['11', '22']
    },
    '41': {
        length: '1',
        data: ['fe']
    },
    '42': {
        length: '2',
        data: ['ef', 'ab']
    },  
}

假设我事先不知道x 中的属性名称是什么。但是,我想检索每个属性及其相关值。如何才能做到这一点?

我正在使用 node.js

【问题讨论】:

标签: javascript json node.js javascript-objects


【解决方案1】:

首先,这不是 JSON。那是一个 JavaScript 对象初始化器。 JSON 是一种 文本 表示法。如果您正在处理 JavaScript 源代码,而不是处理 string,那么您就不是在处理 JSON。 (如果 字符串,则 JSON 无效;JSON 要求键和字符串使用双引号,而不是单引号。)

你可以通过for-inObject.keys找出x对象中的键是什么:

for-in:

var key;
for (key in x) {
    // key is the key
    // x[key] is the value
}

使用最新的 NodeJS,您可以使用 JavaScript 的新 letkey 范围限定为循环:

for (let key in x) {
    // key is the key
    // x[key] is the value
}

Object.keys:

Object.keys(x).forEach(function(key) {
    // key is the key
    // x[key] is the value
});

在 NodeJS 的最新版本中,您可以使用 JavaScript 的新 箭头函数 作为 callbck 以使事情更简洁:

Object.keys(x).forEach(key => {
    // key is the key
    // x[key] is the value
});

如果您需要深入到 x 包含的对象,您只需递归即可。

请注意,for-in 将访问对象的可枚举属性,包括其原型上的任何可枚举属性。 Object.keys 将为您提供对象的自己的可枚举属性的数组(仅限)。

forEach 的示例:

var x = {
    '40': {
        length: '2',
        data: ['11', '22']
    },
    '41': {
        length: '1',
        data: ['fe']
    },
    '42': {
        length: '2',
        data: ['ef', 'ab']
    },  
};
Object.keys(x).forEach(function(key) {
    console.log(key + ": length = " + x[key].length);
});

【讨论】:

  • 谢谢。我更喜欢for-in 方法。看起来更具可读性。但是 Object.keys 更强大吗?看起来它可以做得更多。
  • @LitAiy:使用Object.keys 的好处之一是您可以为keyvalue 变量(回调的范围)提供一个很好的包含范围。但是你也可以使用 JavaScript 的新 let 来实现 for-in
  • 感谢您的回答和解释。很抱歉将答案转给安迪,但他的回答对我的问题更完整。
【解决方案2】:

使用递归查找所有嵌套或其他对象的键/值:

function finder(obj) {

  // for each property in the object passed into
  // the function...
  for (var p in obj) {

    // if its value is another object (see appended note)...
    if (Object.prototype.toString.call(obj[p]).slice(8, -1) === 'Object') {

      // ...log the key to the console and then call finder()
      // again with this current object (this is the recursive part)
      console.log('key: ' + p + ', value: Object');
      finder(obj[p]);

    // otherwise log the key/value
    } else {
      console.log('key: ' + p + ', value: ', obj[p]);
    }
  }
}

finder(x);

输出

key: 40, value: Object
key: length, value:  2
key: data, value:  Array [ "11", "22" ]
key: 41, value: Object
key: length, value:  1
key: data, value:  Array [ "fe" ]
key: 42, value: Object
key: length, value:  2
key: data, value:  Array [ "ef", "ab" ]

注意

这行代码相当冗长,用于检查一个值是否是一个对象

Object.prototype.toString.call(obj[p]).slice(8, -1) === 'Object'

是必要的,因为 typeof obj[p] === 'object' 将返回 true 用于数组和 null 。这有点棘手。

Object.prototype.toString.call({})

返回一个类似"[object Object]" 的字符串,slice 抓取字符串的相关部分。

【讨论】:

  • 谢谢。标记为正确答案。您的回答更完整地回答了我的问题。但我需要一些时间来理解代码。
  • 我会注释给我等一下。
  • 更新了答案@LitAiy。
【解决方案3】:

你可以使用Object.keys():

Object.keys(x).forEach(v => {
    console.log(v);  // logs the key
    console.log(x[v])  // logs the key's value
})

【讨论】:

    【解决方案4】:

    优化安迪的代码

    var x = {
            '40': {
                length: '2',
                data: ['11', '22']
            },
            '41': {
                length: '1',
                data: ['fe']
            },
            '42': {
                length: '2',
                data: ['ef', 'ab']
            },  
        };
    
    
    
    function finder(obj) {
       
      if (Object.prototype.toString.call(obj).slice(8, -1) === 'Object') {
    
        for (var p in obj) {
            console.log('key: ' + p + ', type: object');
            finder(obj[p]);
         } 
      } else {
          console.log('key: ' + obj + ', value: ', obj);
      }
      
    }
    
    finder(x);

    【讨论】:

    • 属性名称lengthdata未知。
    • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
    • 谢谢,我会添加一些
    猜你喜欢
    • 2011-07-04
    • 2017-06-16
    • 1970-01-01
    • 2013-05-10
    • 2022-12-11
    • 2015-07-29
    • 2018-11-28
    • 2010-10-30
    • 1970-01-01
    相关资源
    最近更新 更多