简体   繁体   English

将深度嵌套的结构 object 修改为对象数组

[英]Modify structure of deeply nested object into an array of objects

I have a deeply nested javascript object, which can contain a properties field- which is an object where the key represent the property name and the values represent the rest of the property data.我有一个深度嵌套的 javascript object,它可以包含一个属性字段 - 这是一个 object,其中键代表属性名称,值代表属性数据的 rest。 I want to transform the property object into an array of objects where the key is combined with the values.我想将属性 object 转换为一个对象数组,其中键与值组合在一起。 For example, this is what i have:例如,这就是我所拥有的:

const test = {
    properties: {
      meta: {
        type: 'object',
        properties: {
          agencyId: {
            type: 'string',
            example: 'e767c439-08bf-48fa-a03c-ac4a09eeee8f',
            description: 'agencyId',
          },
        },
      },
      data: {
        type: 'object',
        properties: {
          intervalStartTime: {
            type: 'string',
            description: 'Time in GMT',
            example: '1591702200000',
          },
          group: {
            type: 'object',
            properties: {
              groupType: {
                type: 'string',
                description: 'Group Type',
                example: 'vip',
              },
              numberofRequests: {
                type: 'number',
                example: 10198,
                description: 'Amount of requests coming from group',
              },
            },
          },
        },
      },
    },
  }

And this is what i want:这就是我想要的:

const test = {
  properties: [
    {
      name: 'meta',
      type: 'object',
      properties: [
        [
          {
            type: 'string',
            example: 'e767c439-08bf-48fa-a03c-ac4a09eeee8f',
            description: 'agencyId',
            name: 'agencyId',
          },
        ],
      ],
    },
    {
      name: 'data',
      type: 'object',
      properties: [
        [
          {
            type: 'string',
            description: 'Time in GMT',
            example: '1591702200000',
            name: 'intervalStartTime',
          },
          {
            name: 'group',
            type: 'object',
            properties: [
              {
                name: 'groupType',
                type: 'string',
                description: 'Group Type',
                example: 'vip',
              },
              {
                name: 'numberOfRequests',
                type: 'number',
                example: 10198,
                description: 'Amount of requests coming from group',
              },
            ],
          },
        ],
      ],
    },
  ],
}

I have a helper function that converts the objects into the form that I want, but I am struggling with recursively modifying the nested properties.我有一个助手 function 可以将对象转换成我想要的形式,但我正在努力递归修改嵌套属性。 This is what I have.这就是我所拥有的。 Any suggestions on how I can modify the entire object into the structure that I need?关于如何将整个 object 修改为我需要的结构有什么建议吗?

 const convertObj = (obj) => {
    return Object.entries(obj).reduce((initialVal, [name, nestedProperty]) => {
      initialVal.push({ ...nestedProperty, name })
      return initialVal
    }, [])
  }

 const getNestedProperties = (data) => {
    for (const key in data) {
      const keyDetails = data[key]
      if (keyDetails.hasOwnProperty('properties')) {
        const keyProperties = keyDetails['properties']
        keyDetails['properties'] = []
        keyDetails['properties'].push(convertObj(keyProperties))
        getNestedProperties(keyProperties)
      }
    }
  }

If the object has a properties key, map the entries and create an array of objects with each key as name and rest of the value.如果 object 有一个properties键, map 条目并创建一个对象数组,每个键作为name和 rest 的值。 Loop through the object and check if each property is an object. If yes, recursively call the function. The {...o } part creates a copy of the input, so that it isn't mutated.遍历 object 并检查每个属性是否为 object。如果是,则递归调用 function。 {...o }部分创建输入的副本,因此它不会发生变化。

 const test = {properties:{meta:{type:"object",properties:{agencyId:{type:"string",example:"e767c439-08bf-48fa-a03c-ac4a09eeee8f",description:"agencyId",},},},data:{type:"object",properties:{intervalStartTime:{type:"string",description:"Time in GMT",example:"1591702200000",},group:{type:"object",properties:{groupType:{type:"string",description:"Group Type",example:"vip",},numberofRequests:{type:"number",example:10198,description:"Amount of requests coming from group",}}}}}}}; function convert({...o }) { for (const key in o) { if (typeof o[key] === 'object') o[key] = convert(o[key]) } if (o.hasOwnProperty("properties")) o.properties = Object.entries(o.properties).map(([name, v]) => ({ name, ...v })) return o } console.log(convert(test))

If you have no properties property, just return the rest of the object. If you do, return the rest of the object plus a properties array property formed by taking each name-value entry in that property and converting it into an object by adding the property name to the result of calling transform on that value .如果您没有properties属性,只需返回 object 的 rest。如果有,则返回 object 的 rest 加上一个properties数组属性,该属性数组属性通过获取该属性中的每个名称-值条目并将其转换为 object 通过添加属性name到对该value调用transform的结果。

The code is fairly simple:代码相当简单:

 const transform = ({properties, ...rest} = {}) => properties? {... rest, properties: Object.entries (properties).map (([name, val]) => ({ name, ... transform (val) })) }: {... rest} const test = {properties: {meta: {type: 'object', properties: {agencyId: {type: 'string', example: 'e767c439-08bf-48fa-a03c-ac4a09eeee8f', description: 'agencyId'}}}, data: {type: 'object', properties: {intervalStartTime: {type: 'string', description: 'Time in GMT', example: '1591702200000'}, oup: {type: 'object', properties: {grupType: {type: 'string', description: 'Group Type', example: 'vip'}, numberofRequests: { type: 'number', example: 10198, description: 'Amount of requests coming from group'}}}}}}} console.log (transform (test))
 .as-console-wrapper {max-height: 100%;important: top: 0}

Here is a solution where object-scan does the heavy lifting.这是一个解决方案,其中对象扫描完成了繁重的工作。 Note that this works because traversal happens in delete safe order.请注意,这是有效的,因为遍历发生在删除安全顺序中。

 // const objectScan = require('object-scan'); const test = { properties: { meta: { type: 'object', properties: { agencyId: { type: 'string', example: 'e767c439-08bf-48fa-a03c-ac4a09eeee8f', description: 'agencyId' } } }, data: { type: 'object', properties: { intervalStartTime: { type: 'string', description: 'Time in GMT', example: '1591702200000' }, group: { type: 'object', properties: { groupType: { type: 'string', description: 'Group Type', example: 'vip' }, numberofRequests: { type: 'number', example: 10198, description: 'Amount of requests coming from group' } } } } } } }; const rewrite = (obj) => objectScan(['**.properties'], { rtn: 'count', // returns number of rewrites filterFn: ({ value, parent, property }) => { parent[property] = Object.entries(value).map(([name, v]) => ({ name, ...v })); } })(obj); console.log(rewrite(test)); // => 4 console.log(test); // => { properties: [ { name: 'meta', type: 'object', properties: [ { name: 'agencyId', type: 'string', example: 'e767c439-08bf-48fa-a03c-ac4a09eeee8f', description: 'agencyId' } ] }, { name: 'data', type: 'object', properties: [ { name: 'intervalStartTime', type: 'string', description: 'Time in GMT', example: '1591702200000' }, { name: 'group', type: 'object', properties: [ { name: 'groupType', type: 'string', description: 'Group Type', example: 'vip' }, { name: 'numberofRequests', type: 'number', example: 10198, description: 'Amount of requests coming from group' } ] } ] } ] }
 .as-console-wrapper {max-height: 100%;important: top: 0}
 <script src="https://bundle.run/object-scan@13.7.1"></script>

Disclaimer : I'm the author of object-scan免责声明:我是对象扫描的作者

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

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