簡體   English   中英

根據可作為數組使用的動態鍵更新json對象中的值

[英]Update values in a json object based on dynamic keys available as array

我有一個像這樣的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。

您可以通過沿着路徑減少對象。

 function getValue(object, path) { return path.reduce(function (o, k) { return (o || {})[k]; }, object); } var object = { 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" } } } } }; console.log(getValue(object, ['glossary', 'GlossDiv', 'GlossList', 'GlossEntry', 'SortAs'])); 

盡管您使用的是Underscore,但Lodash與Backbone 100%兼容,並且可以替換_.get並為您的特定情況提供_.get_.set

路徑可以在數組中,也可以是字符串。 它甚至處理訪問數組索引。

_.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, 'abc', 'default'); // => 'default' 

_.set沿路徑創建丟失的對象和數組(如果不存在)。

_.set(object, path, value)
 _.set(object, 'a[0].b.c', 4); console.log(object.a[0].bc); // => 4 _.set(object, ['x', '0', 'y', 'z'], 5); console.log(object.x[0].yz); // => 5 

甚至還有一個_.result函數,如果它是一個函數,它將調用該值。

_.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' 

根據Nina的答案 ,要設置值,您可以執行以下操作,使其路徑在最后一個鍵之前停止,並使用最后一個鍵手動更新對象。

 function getValue(object, path) { return path.reduce(function (o, k) { return (o || {})[k]; }, object); } 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" } } } } }; var target = getValue(obj, ['glossary', 'GlossDiv']); target.title = "test"; console.log(obj); 

或作為一個新函數,它直接獲取一個值並完成所有工作。

 function setValue(object, path, value) { var target = path.slice(0, -1).reduce(function(obj, key) { return (obj || {})[key]; }, object); target[path[path.length-1]] = value; } 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" } } } } }; setValue(obj, ['glossary', 'GlossDiv', 'GlossList', 'GlossEntry', 'GlossSee'], "my test value"); console.log(obj); 

妮娜的答案將是我這樣做的首選方式。 對於那些還不熟悉函數式編程或精簡的人,簡單的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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM