JSON 中的嵌套 Key/Value 结构

Nested Key/Value Structures in JSON

我从服务中得到以下 JSON 结构:

{
    "prop": [
        {
            "key": "FOO",
            "value": "Foo is wonderfull, foo is great"
        },
        {
            "key": "BAR",
            "value": "Bar is bad, really bad"
        }
    ]
}

我需要一个函数,它作为参数,例如BAR 和输出 "Bar is bad,..",我该如何实现? Lodash/underscore 或 VanillaJS 欢迎使用。

我写在JAVASCRIPT:

var d = {
  "prop": [{
    "key": "FOO",
    "value": "Foo is wonderfull, foo is great"
  }, {
    "key": "BAR",
    "value": "Bar is bad, really bad"
  }]
}

obj = d;
parm = 'BAR'
for (item in obj["prop"]) {
  if (parm == item['key']) {
    console.log(item['value'])
  }
}

查看步骤:-

  • 首先将JSON解析为对象
  • 然后遍历 "prop"
  • 将密钥与参数进行比较 ("BAR")
  • 如果匹配打印值

您可以使用 Array#some 并在找到值后结束迭代。

function getValue(array, key) {
    var value;
    array.some(function (a) {
        if (a.key === key) {
            value = a.value;
            return true;
        }
    });
    return value;
}

var object = { "prop": [{ "key": "FOO", "value": "Foo is wonderfull, foo is great" }, { "key": "BAR", "value": "Bar is bad, really bad" }] };

console.log(getValue(object.prop, 'BAR'));

ES6 与 Array#find

function getValue(array, key) {
    return (array.find(a => a.key === key) || {}).value;
}

var object = { "prop": [{ "key": "FOO", "value": "Foo is wonderfull, foo is great" }, { "key": "BAR", "value": "Bar is bad, really bad" }] };

console.log(getValue(object.prop, 'BAR'));

您可以使用 Array.find 找到必要的对象,然后 return 它的值

var d = {
  "prop": [{
    "key": "FOO",
    "value": "Foo is wonderfull, foo is great"
  }, {
    "key": "BAR",
    "value": "Bar is bad, really bad"
  }]
}

function FindValue(value) {
  var _tmp = d.prop.find(function(o) {
    return o.key === value
  });
  return _tmp ? _tmp.value : "No object found";
}

console.log(FindValue("BAR"));
console.log(FindValue("BAR1"));
console.log(FindValue("FOO"));


编辑 1

按照 @Benny Bottema, Array.find has compatibility issues. You can either add a polyfill 的建议,或者您可以使用其他方法,例如 Array.filterArray.forEach 但请注意,即使这些方法在 IE8 中也不支持。

如果要使其与所有浏览器兼容,您应该使用 forfor..in,因为它们是跨浏览器的标准。

版本

var d = {
  "prop": [{
    "key": "FOO",
    "value": "Foo is wonderfull, foo is great"
  }, {
    "key": "BAR",
    "value": "Bar is bad, really bad"
  }]
}

function FindValue(value) {
  for (var i=0;i<d.prop.length;i++){
    if(d.prop[i].key === value) return d.prop[i].value;
  }
}

console.log(FindValue("BAR"));
console.log(FindValue("BAR1"));
console.log(FindValue("FOO"));


for..in版本

注意,for..in更适合循环对象的键。

var d = {
  "prop": [{
    "key": "FOO",
    "value": "Foo is wonderfull, foo is great"
  }, {
    "key": "BAR",
    "value": "Bar is bad, really bad"
  }]
}

function FindValue(value) {
  for (var i in d.prop){
    if(d.prop[i].key === value) return d.prop[i].value;
  }
}

console.log(FindValue("BAR"));
console.log(FindValue("BAR1"));
console.log(FindValue("FOO"));


for..of版本

如果你使用的是 ES6,那么你甚至可以尝试 for..of

var d = {
  "prop": [{
    "key": "FOO",
    "value": "Foo is wonderfull, foo is great"
  }, {
    "key": "BAR",
    "value": "Bar is bad, really bad"
  }]
}

function FindValue(value) {
  for (var _o of d.prop){
    if(_o.key === value) return _o.value;
  }
}

console.log(FindValue("BAR"));
console.log(FindValue("BAR1"));
console.log(FindValue("FOO"));


参考资料

现代纯正javascript:

function getValue(theObject, keyValue) {
  return theObject.prop
    .filter(function(x){ // find all elements with the wanted key
      return x.key == keyValue;
    })
    .map(function(x){ // return only the value
      return x.value;
    })[0]; // Assuming no duplicate keys just return first item
}

注意:数组方法 .filter().map() return 数组。

老式 for 循环:

function getValue(theObject, keyValue) {
  var p = theObject.prop;

  for (var i=0; i<p.length; i++) {
    var item = p[i];
    if (item.key == keyValue) {
      return item.value;
    }
  }
}

有趣的是,这比上面的第一种方法更快,因为它在找到匹配项后立即停止处理 prop 数组。

var filteredArray = { "prop": [{ "key": "FOO", "value": "Foo is wonderfull, foo is great" }, { "key": "BAR", "value": "Bar is bad, really bad" }] };
function getByKey(findKey,filteredArray){
    if(filteredArray.length){
            var result = filteredArray.filter(function(x){
                return x.key === findKey
            });
            if(result && result.length){return result[0].value}
    }
}
getByKey('BAR',filteredArray.prop)

但是函数只会return第一个过滤对象的值;

您可以使用lodash#find按键获取值。

function getValueByKey(array, key) {
  return (_.find(array, { key: key }) || {}).value;
}

var result = getValueByKey(data.prop, 'BAR');

var data = {
    "prop": [
        {
            "key": "FOO",
            "value": "Foo is wonderfull, foo is great"
        },
        {
            "key": "BAR",
            "value": "Bar is bad, really bad"
        }
    ]
};

function getValueByKey(array, key) {
  return (_.find(array, { key: key }) || {}).value;
}

var result = getValueByKey(data.prop, 'BAR');

console.log(result);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>

简单。

Lodash

var data = {
    "prop": [
        {
            "key": "FOO",
            "value": "Foo is wonderfull, foo is great"
        },
        {
            "key": "BAR",
            "value": "Bar is bad, really bad"
        }
    ]
}

function getValueForKey(key) {
  return _.result(_.find(data.prop, { key: key }), 'value') || "unknown key: " + key;
}

document.write(getValueForKey("FOO") + "<br/>");
document.write(getValueForKey("BAR") + "<br/>");
document.write(getValueForKey("FOOBAR"));
<script src="https://cdn.rawgit.com/lodash/lodash/4.13.1/dist/lodash.core.min.js"></script>

下划线

var data = {
    "prop": [
        {
            "key": "FOO",
            "value": "Foo is wonderfull, foo is great"
        },
        {
            "key": "BAR",
            "value": "Bar is bad, really bad"
        }
    ]
}

function getValueForKey(key) {
  return _.result(_.find(data.prop, { key: key }), 'value', "unknown key: " + key);
}

document.write(getValueForKey("FOO") + "<br/>");
document.write(getValueForKey("BAR") + "<br/>");
document.write(getValueForKey("FOOBAR"));
<script src="http://underscorejs.org/underscore.js"></script>

Plain javascript(使用filter,主流浏览器支持)

var data = {
    "prop": [
        {
            "key": "FOO",
            "value": "Foo is wonderfull, foo is great"
        },
        {
            "key": "BAR",
            "value": "Bar is bad, really bad"
        }
    ]
}

function getValueForKey(key) {
  var prop = data.prop.filter(function(prop) { return prop.key === key})[0];
  return prop ? prop.value : "unknown key: " + key;
}

document.write(getValueForKey("FOO") + "<br/>");
document.write(getValueForKey("BAR") + "<br/>");
document.write(getValueForKey("FOOBAR"));

Plain javascript(使用 find,目前主要使用 polyfill)

var data = {
    "prop": [
        {
            "key": "FOO",
            "value": "Foo is wonderfull, foo is great"
        },
        {
            "key": "BAR",
            "value": "Bar is bad, really bad"
        }
    ]
}

function getValueForKey(key) {
  var prop = data.prop.find(function(prop) { return prop.key === key });
  return prop ? prop.value : "unknown key: " + key;
}

document.write(getValueForKey("FOO") + "<br/>");
document.write(getValueForKey("BAR") + "<br/>");
document.write(getValueForKey("FOOBAR"));
<script>
// polyfill from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill
if (!Array.prototype.find) {
  Array.prototype.find = function(predicate) {
    if (this == null) {
      throw new TypeError('Array.prototype.find called on null or undefined');
    }
    if (typeof predicate !== 'function') {
      throw new TypeError('predicate must be a function');
    }
    var list = Object(this);
    var length = list.length >>> 0;
    var thisArg = arguments[1];
    var value;

    for (var i = 0; i < length; i++) {
      value = list[i];
      if (predicate.call(thisArg, value, i, list)) {
        return value;
      }
    }
    return undefined;
  };
}
</script>

Plain javascript(使用旧式 for 循环)

var data = {
    "prop": [
        {
            "key": "FOO",
            "value": "Foo is wonderfull, foo is great"
        },
        {
            "key": "BAR",
            "value": "Bar is bad, really bad"
        }
    ]
}

function getValueForKey(key) {
  for (var i = 0; i < data.prop.length; i++) {
    if (data.prop[i].key === key) {
      return data.prop[i].value;
    }
    return "unknown key: " + key;
  }
}

document.write(getValueForKey("FOO") + "<br/>");
document.write(getValueForKey("BAR") + "<br/>");
document.write(getValueForKey("FOOBAR"));