基于可用作数组的动态键更新json对象中的值

时间:2016-11-03 15:51:03

标签: javascript json

我有一个像这样的json对象:

var obj = {
    "glossary": {
        "title": "example glossary",
        "GlossDiv": {
            "title": "S",
            "GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
                    "SortAs": "SGML",
                    "GlossTerm": "Standard Generalized Markup Language",
                    "Acronym": "SGML",
                    "Abbrev": "ISO 8879:1986",
                    "GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
                        "GlossSeeAlso": ["GML", "XML"]
                    },
                    "GlossSee": "markup"
                }
            }
        }
    }
}

此JSON可以是任何有效的JSON。现在我想基于可用的数组访问和更新一些属性,如下所示:

['glossary', 'GlossDiv', 'GlossList', 'GlossEntry', 'SortAs'] // any dynamic but valid path

所以给定上面的数组,我想访问

obj['glossary']['GlossDiv']['GlossList']['GlossEntry']['SortAs']

这样我就可以更新它的价值了。我有config(or any such json)作为实例变量,所以我想直接更新它而不是创建一个新的json,然后替换整个config对象。我可以访问jQuery,下划线,主干,当然还有普通的JS。

3 个答案:

答案 0 :(得分:2)

你可以通过走路来减少对象。



$scope




答案 1 :(得分:1)

虽然您使用的是Underscore,但Lodash与Backbone 100%兼容并且可以取代Underscore,并且针对您的特定情况提供_.get_.set

路径可以在数组中,也可以是字符串。它甚至处理访问数组索引。

    def httpResponseHeaders = context.testCase.testSteps["Testname"].testRequest.response.responseHeaders
    //log.info (httpResponseHeaders)
    httpResponseHeaders.each
    {
      k,v ->
        if(k=~"X-Duration-MS"){
          assert k == "X-Duration-MS"
      }
    }
public static void main(String[] args) {
    System.out.println("Please insert 3 numbers: ");
    Scanner number = new Scanner(System.in);

    Integer[] input = new Integer[3];
    int i = 0;
    while (i != 3) {
        input[i++] = number.nextInt();
    }
    number.close();
    Arrays.sort(input, Collections.reverseOrder());
    StringBuffer sb = new StringBuffer();
    for (Integer a : input) {
        sb.append(a).append(">");
    }
    System.out.println(sb.substring(0, sb.length() - 1));
}

_.get(object, path, [defaultValue]) 在路径中创建缺少的对象和数组(如果它们不存在)。

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// => 3

_.get(object, ['a', '0', 'b', 'c']);
// => 3

_.get(object, 'a.b.c', 'default');
// => 'default'
_.set

甚至还有一个_.set(object, path, value) 函数,如果它是一个函数,它会调用该值。

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4

_.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object.x[0].y.z);
// => 5
_.result

根据Nina's answer,要设置值,您可以执行以下操作,在最后一个键之前有一个停止的路径,并使用最后一个键手动更新对象。



_.result(object, path, [defaultValue])




或者作为一个新功能,它直接获取一个值并完成所有工作。



var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };

_.result(object, 'a[0].b.c1');
// => 3

_.result(object, 'a[0].b.c2');
// => 4

_.result(object, 'a[0].b.c3', 'default');
// => 'default'

_.result(object, 'a[0].b.c3', _.constant('default'));
// => 'default'




答案 2 :(得分:0)

Nina's answer将是我这样做的首选方式。对于那些还不熟悉函数式编程或缩减的人来说,一个简单的forEach就可以解决问题。比较好。

var config = {
  name: "foo",
  email: "bar",
  photo: {
    small: "somelink",
    large: "largelink"
  }
};

var keys = ['photo', 'large'];
var prevRef = config, ref;

keys.forEach(function(val, index) {
  console.log(val);
  ref = prevRef[val];
  prevRef = ref;
});

console.log(ref);