如何向 JavaScript 中嵌套 JSON 结构中的每个对象添加 属性?
How to add a property to every object in a nested JSON structure in JavaScript?
假设我有一个 API 响应,如下所示:
const data = {
users: [
{ name: "John", teams: [{ name: "Liverpool" }] },
{ name: "Sam", teams: [{ name: "MC" }, { name: "United" }] },
],
photos: [
{ id: "123", types: ["JPG", "PNG"], comments: [{ description: "sample photo" }] },
],
};
我想通过将 rid
属性 添加到每个 object.
来转换它
const data = {
rid: "ABC",
users: [
{ rid: "ABC", name: "John", teams: [{ rid: "ABC", name: "Liverpool" }] },
{ rid: "ABC", name: "Sam", teams: [{ rid: "ABC", name: "MC" }, { rid: "ABC", name: "United" }] },
],
photos: [
{ rid: "ABC", id: "123", types: ["JPG", "PNG"], comments: [{ rid: "ABC", description: "sample photo" }] },
],
};
我该怎么做?我认为其中涉及某种递归,但我无法起草解决方案?
谢谢。
首先,OP 不会改变 JSON 对象。 JSON
是基于字符串的标准化数据交换格式和具有静态方法的 JavaScript 命名空间。
但是 OP 将递归地 traverse/walk a JSON-conform object-type.
因此这样一个函数的实现只需要考虑 object-types 和数组。
在 array-type 的情况下, 递归调用 发生在对象自己的可枚举 keys/propertiesforEach
array-item. In case of an object-type all values
=40=]会被递归处理。
对于任何 object-type,另外 assign
ment 提供的自定义对象(一个或多个条目)发生。
下面提供的函数提供了定义最小值的可能性 object-level 从哪里开始应用赋值。
function recursivelyAssignDataToEveryObjectType(type, data, startLevel = 0, level = 0) {
if (Array.isArray(type)) {
type
.forEach(item =>
recursivelyAssignDataToEveryObjectType(item, data, startLevel, level + 1)
);
} else if (type && 'object' === typeof type) {
Object
.values(type)
.forEach(value =>
recursivelyAssignDataToEveryObjectType(value, data, startLevel, level + 1)
);
if (level >= startLevel) {
Object.assign(type, data);
}
}
}
const data = {
users: [
{ name: "John", teams: [{ name: "Liverpool" }] },
{ name: "Sam", teams: [{ name: "MC" }, { name: "United" }] },
],
photos: [
{ id: "123", types: ["JPG", "PNG"], comments: [{ description: "sample photo" }] },
],
};
recursivelyAssignDataToEveryObjectType(data, { rid: "ABC" }, 2);
console.log({ data });
.as-console-wrapper { min-height: 100%!important; top: 0; }
你只需要用递归函数遍历对象即可。
试试下面的代码片段。
const data = {
users: [
{ name: 'John', teams: [{ name: 'Liverpool' }] },
{ name: 'Sam', teams: [{ name: 'MC' }, { name: 'United' }] },
],
photos: [
{ id: '123', types: ['JPG', 'PNG'], comments: [{ description: 'sample photo' }] },
{ key: null }, // Fixed null values
],
}
function addProperty(obj, key, val) {
if (!obj || typeof obj !== 'object') return
if (!Array.isArray(obj)) obj[key] = val
Object.values(obj).forEach((obj) => addProperty(obj, key, val))
}
addProperty(data, 'rid', 'ABC')
console.log(data)
首先,在 Whosebug 中,您应该始终展示自己的作品。即使您无法获得完整的解决方案,也请向我们展示您的尝试并告诉我们似乎哪里出了问题。我不会回答这个问题,除非这里已经有其他两个合理的答案。
我非常反感修改输入数据,所以我写了一个版本,创建了一个副本,其中 属性 包含在所有 Object
节点上。它看起来像这样:
const addProp = (name, val) => (o) =>
Array .isArray (o)
? o .map (addProp (name, val))
: Object (o) === o
? Object .fromEntries ([
[name, val],
...Object .entries (o) .map (([k, v]) => [k, addProp (name, val) (v)])
])
: o
const data = {users: [{name: "John", teams: [{name: "Liverpool"}]}, {name: "Sam", teams: [{name: "MC"}, {name: "United"}]},], photos: [{id: "123", types: ["JPG", "PNG"], comments: [{description: "sample photo"}]}]}
console .log (addProp ('rid', 'ABC') (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
我们根据输入是 Array
、Object
还是其他内容,以三种方式进行处理。如果两者都不是,我们 return 值保持不变。如果它是一个数组,我们将递归调用映射到其值上的同一函数。对于一个对象,我们将它分成 name-value 对,通过递归调用映射值并为我们的新 属性 添加一个,然后我们将这些 name-value 条目折叠回一个对象。
假设我有一个 API 响应,如下所示:
const data = {
users: [
{ name: "John", teams: [{ name: "Liverpool" }] },
{ name: "Sam", teams: [{ name: "MC" }, { name: "United" }] },
],
photos: [
{ id: "123", types: ["JPG", "PNG"], comments: [{ description: "sample photo" }] },
],
};
我想通过将 rid
属性 添加到每个 object.
const data = {
rid: "ABC",
users: [
{ rid: "ABC", name: "John", teams: [{ rid: "ABC", name: "Liverpool" }] },
{ rid: "ABC", name: "Sam", teams: [{ rid: "ABC", name: "MC" }, { rid: "ABC", name: "United" }] },
],
photos: [
{ rid: "ABC", id: "123", types: ["JPG", "PNG"], comments: [{ rid: "ABC", description: "sample photo" }] },
],
};
我该怎么做?我认为其中涉及某种递归,但我无法起草解决方案?
谢谢。
首先,OP 不会改变 JSON 对象。 JSON
是基于字符串的标准化数据交换格式和具有静态方法的 JavaScript 命名空间。
但是 OP 将递归地 traverse/walk a JSON-conform object-type.
因此这样一个函数的实现只需要考虑 object-types 和数组。
在 array-type 的情况下, 递归调用 发生在对象自己的可枚举 keys/propertiesforEach
array-item. In case of an object-type all values
=40=]会被递归处理。
对于任何 object-type,另外 assign
ment 提供的自定义对象(一个或多个条目)发生。
下面提供的函数提供了定义最小值的可能性 object-level 从哪里开始应用赋值。
function recursivelyAssignDataToEveryObjectType(type, data, startLevel = 0, level = 0) {
if (Array.isArray(type)) {
type
.forEach(item =>
recursivelyAssignDataToEveryObjectType(item, data, startLevel, level + 1)
);
} else if (type && 'object' === typeof type) {
Object
.values(type)
.forEach(value =>
recursivelyAssignDataToEveryObjectType(value, data, startLevel, level + 1)
);
if (level >= startLevel) {
Object.assign(type, data);
}
}
}
const data = {
users: [
{ name: "John", teams: [{ name: "Liverpool" }] },
{ name: "Sam", teams: [{ name: "MC" }, { name: "United" }] },
],
photos: [
{ id: "123", types: ["JPG", "PNG"], comments: [{ description: "sample photo" }] },
],
};
recursivelyAssignDataToEveryObjectType(data, { rid: "ABC" }, 2);
console.log({ data });
.as-console-wrapper { min-height: 100%!important; top: 0; }
你只需要用递归函数遍历对象即可。
试试下面的代码片段。
const data = {
users: [
{ name: 'John', teams: [{ name: 'Liverpool' }] },
{ name: 'Sam', teams: [{ name: 'MC' }, { name: 'United' }] },
],
photos: [
{ id: '123', types: ['JPG', 'PNG'], comments: [{ description: 'sample photo' }] },
{ key: null }, // Fixed null values
],
}
function addProperty(obj, key, val) {
if (!obj || typeof obj !== 'object') return
if (!Array.isArray(obj)) obj[key] = val
Object.values(obj).forEach((obj) => addProperty(obj, key, val))
}
addProperty(data, 'rid', 'ABC')
console.log(data)
首先,在 Whosebug 中,您应该始终展示自己的作品。即使您无法获得完整的解决方案,也请向我们展示您的尝试并告诉我们似乎哪里出了问题。我不会回答这个问题,除非这里已经有其他两个合理的答案。
我非常反感修改输入数据,所以我写了一个版本,创建了一个副本,其中 属性 包含在所有 Object
节点上。它看起来像这样:
const addProp = (name, val) => (o) =>
Array .isArray (o)
? o .map (addProp (name, val))
: Object (o) === o
? Object .fromEntries ([
[name, val],
...Object .entries (o) .map (([k, v]) => [k, addProp (name, val) (v)])
])
: o
const data = {users: [{name: "John", teams: [{name: "Liverpool"}]}, {name: "Sam", teams: [{name: "MC"}, {name: "United"}]},], photos: [{id: "123", types: ["JPG", "PNG"], comments: [{description: "sample photo"}]}]}
console .log (addProp ('rid', 'ABC') (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
我们根据输入是 Array
、Object
还是其他内容,以三种方式进行处理。如果两者都不是,我们 return 值保持不变。如果它是一个数组,我们将递归调用映射到其值上的同一函数。对于一个对象,我们将它分成 name-value 对,通过递归调用映射值并为我们的新 属性 添加一个,然后我们将这些 name-value 条目折叠回一个对象。