简体   繁体   English

如何为 JavaScript 中嵌套 JSON 结构中的每个对象添加属性?

[英]How to add a property to every object in a nested JSON structure in JavaScript?

Let's suppose I have an API response that looks like this:假设我有一个如下所示的 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" }] },
  ],
};

I want to transform it by adding the rid property to each object .我想通过将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" }] },
  ],
};

How can I do so?我该怎么做? I think there is some kind of recursion involved but I haven't been able to draft a solution?我认为涉及某种递归,但我无法起草解决方案?

Thanks.谢谢。

First off, in StackOverflow, you should always show your own work.首先,在 StackOverflow 中,您应该始终展示自己的工作。 Even if you weren't able to get a complete solution, please show us what you've tried and tell us where it seemed to go wrong.即使您无法获得完整的解决方案,也请向我们展示您的尝试并告诉我们哪里出了问题。 I would not be answering this question except that there are already two other reasonable answers here.我不会回答这个问题,除非这里已经有另外两个合理的答案。


I have a strong aversion to modifying input data, so I wrote a version that creates a copy with that property included on all Object nodes.我对修改输入数据有强烈的反感,因此我编写了一个版本,该版本创建了一个副本,该副本包含在所有Object节点上的该属性。 It looks like this:它看起来像这样:

 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}

We process in three ways, based on whether our input is an Array , an Object , or something else.根据我们的输入是ArrayObject还是其他东西,我们以三种方式进行处理。 If it's neither, we return the value intact.如果两者都不是,我们将原样返回值。 If it's an array, we map a recursive call to the same function over its values.如果它是一个数组,我们将递归调用映射到其值上的同一函数。 For an object, we split it into name-value pairs, mapping the values with a recursive call and adding one for our new property, then we fold these name-value entries back into an object.对于一个对象,我们将其拆分为名称-值对,通过递归调用映射值并为我们的新属性添加一个,然后我们将这些名称-值条目折叠回一个对象。

Firstly the OP is not going to alter a JSON object.首先,OP 不会更改 JSON 对象。 JSON is a string based standardized data interchange format and a JavaScript namespace with static methods. JSON是一种基于字符串的标准化数据交换格式和带有静态方法的 JavaScript 命名空间。

But the OP is going to recursively traverse/walk a JSON-conform object-type.但是 OP 将递归遍历/遍历符合 JSON 的对象类型。

Thus the implementation of such a function needs to take into account just object-types and arrays.因此,这样一个函数的实现只需要考虑对象类型和数组。

In case of an array-type the recursive call takes place forEach array-item .在数组类型的情况下,递归调用发生在forEach array-item In case of an object-type all values of the object's own enumerable keys/properties will be processed recursively.在对象类型的情况下,对象自己的可枚举键/属性的所有values将被递归处理。

For any object-type in addition the assign ment of a provided custom object (one or more entries) takes place.此外,对于任何对象类型,都会assign所提供的自定义对象(一个或多个条目)。

The beneath provided function provides as feature the possibility to define the minimum object-level from where an assignement is going to be applied.下面提供的功能提供了定义要应用分配的最小对象级别的可能性。

 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; }

You just need to iterate through object with recursive function.您只需要使用递归函数遍历对象。

Try below snippet.试试下面的片段。

 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM