[英]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.