我使用此代码从sJhonny's Question
中查找json对象所需的部分数据样本
TestObj = {
"Categories": [{
"Products": [{
"id": "a01",
"name": "Pine",
"description": "Short description of pine."
},
{
"id": "a02",
"name": "Birch",
"description": "Short description of birch."
},
{
"id": "a03",
"name": "Poplar",
"description": "Short description of poplar."
}],
"id": "A",
"title": "Cheap",
"description": "Short description of category A."
},
{
"Product": [{
"id": "b01",
"name": "Maple",
"description": "Short description of maple."
},
{
"id": "b02",
"name": "Oak",
"description": "Short description of oak."
},
{
"id": "b03",
"name": "Bamboo",
"description": "Short description of bamboo."
}],
"id": "B",
"title": "Moderate",
"description": "Short description of category B."
}]
};
查找功能
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
}
像这样使用:
getObjects(TestObj, 'id', 'A'); // Returns an array of matching objects
此代码用于从源中选择匹配的片段。但我想要的是用新值更新源对象并检索更新的源对象。
我想要像
这样的东西getObjects(TestObj, 'id', 'A', 'B'); // Returns source with updated value. (ie id:'A' updated to id:'B' in the returned object)
我的代码
function getObjects(obj, key, val, newVal) {
var newValue = newVal;
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
obj[key] = 'qwe';
}
}
return obj;
}
如果我提供obj[key] = 'qwe';
,但是如果我将代码更改为obj[key] = newValue;
,则将其更新为未定义。
为什么会这样?
答案 0 :(得分:10)
您忘记在嵌套调用中传递newValue
function getObjects(obj, key, val, newVal) {
var newValue = newVal;
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val, newValue));
} else if (i == key && obj[key] == val) {
obj[key] = 'qwe';
}
}
return obj;
}
答案 1 :(得分:2)
这个?
function update(obj, key, newVal) {
for(var i in obj) {
if(typeof obj[i] == 'object') {
update(obj[i], key, newVal));
} else if(i === key) {
obj[i] = newVal;
}
}
return obj;
}
答案 2 :(得分:1)
function getObjects(obj, key, val, newVal) {
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (i == key && obj[key] == val) {
obj[key] = newVal;
}
}
return obj
}
这将使用newValue(newVal)
对找到的值进行就地更新答案 3 :(得分:0)
您可以尝试我的解决方案
const InsertOrUpdate = (dest, src) => {
GetValue(dest, src, [])
}
const GetValue = (dest, src, keys) => {
for (let key in src) {
let srcValue = src[key]
// Don't use push here
// The concat() method does not change the existing arrays, but returns a new array, containing the values of the joined arrays
let parentKeys = keys.concat(key)
if (typeof (srcValue) === 'object') {
GetValue(dest, srcValue, parentKeys)
} else {
SetValue(dest, parentKeys, srcValue)
}
}
}
const SetValue = (dest, keys, value) => {
if (!keys.length || keys.length === 0) {
return
}
let key = keys[0]
let childKeys = keys.slice(1)
// update
// note: null is object
if (dest[key] && typeof (dest[key]) === 'object') {
SetValue(dest[key], childKeys, value)
} else {
// insert
if (childKeys.length === 0) {
dest[key] = value
} else {
// insert parent key & continue update
dest[key] = {}
SetValue(dest[key], childKeys, value)
}
}
}
答案 4 :(得分:0)
我尝试使用上面选择的解决方案,但是它将使用相同的值更新每一行。因此,我添加了一种定义要更新的记录的方法,并且还提供了一种方法,一旦您经过它,就可以跟踪当前记录ID。
function getObjects(obj, rowId, key, val, newVal, rId) {
var objects = [];
for (var i in obj) {
if(obj[i].id !== undefined) rId = obj[i].id;
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(this.updateObject(obj[i], rowId, key, val, newVal, rId));
} else if (i == key && obj[key] == val) {
if(rId == rowId) obj[key] = newVal;
}
}
return obj;
}
答案 5 :(得分:0)
看看object-scan。现在,我们将其用于大量数据处理。对我们来说,它使代码更易于维护,只需花一点时间就可以解决问题。这是您如何回答问题的方法
const objectScan = require('object-scan');
const update = (data, needle, from, to) => objectScan([needle], {
abort: true,
rtn: 'bool',
filterFn: ({ value, parent, property }) => {
if (value === from) {
parent[property] = to;
return true;
}
return false;
}
})(data);
// -------------------------------
const TestObj = {"Categories":[{"Products":[{"id":"a01","name":"Pine","description":"Short description of pine."},{"id":"a02","name":"Birch","description":"Short description of birch."},{"id":"a03","name":"Poplar","description":"Short description of poplar."}],"id":"A","title":"Cheap","description":"Short description of category A."},{"Product":[{"id":"b01","name":"Maple","description":"Short description of maple."},{"id":"b02","name":"Oak","description":"Short description of oak."},{"id":"b03","name":"Bamboo","description":"Short description of bamboo."}],"id":"B","title":"Moderate","description":"Short description of category B."}]};
console.log(update(TestObj, '**.id', 'A', 'B'));
// => true
console.log(JSON.stringify(TestObj));
// => {"Categories":[{"Products":[{"id":"a01","name":"Pine","description":"Short description of pine."},{"id":"a02","name":"Birch","description":"Short description of birch."},{"id":"a03","name":"Poplar","description":"Short description of poplar."}],"id":"B","title":"Cheap","description":"Short description of category A."},{"Product":[{"id":"b01","name":"Maple","description":"Short description of maple."},{"id":"b02","name":"Oak","description":"Short description of oak."},{"id":"b03","name":"Bamboo","description":"Short description of bamboo."}],"id":"B","title":"Moderate","description":"Short description of category B."}]}