【问题标题】:recursively flatten objects in nested objects and arrays javascript递归地展平嵌套对象和数组中的对象javascript
【发布时间】:2018-04-20 22:52:57
【问题描述】:

我有一个很大的 JSON 对象,它可能是不规则的,我想要找到一种方法将它的所有对象放在一个平面数组中。

这是一个示例 json:

{
    "name":"getPost",
    "request":{
        "type":"object",
        "fields":[{
            "key":"id",
            "value":{"type":"string"}
        }]
    },
    "response":{
        "type":"object",
        "fields":[{
            "key":"post",
            "value":{
                "type":"object",
                "fields":[{
                    "key":"id",
                    "value":{"type":"string"}
                },{
                    "key":"title",
                    "value":{"type":"string"}
                },{
                    "key":"content",
                    "value":{"type":"string"}
                },{
                    "key":"userId",
                    "value":{"type":"string"}
                }]
            }
        }]
    },
    "error":[]
}

我希望它变成这样:(我只需要具有浅键值的对象)

[
    {
        "key":"id",
        "value":{"type":"string"}
    },{
        "key":"post",
        "value":{"type":"object"}
    },{
        "key":"id",
        "value":{"type":"string"}
    },{
        "key":"title",
        "value":{"type":"string"}
    },{
        "key":"content",
        "value":{"type":"string"}
    },{
        "key":"userId",
        "value":{"type":"string"}
    }
]

我需要知道在没有 ES6 的情况下是否有一种简单的方法。

【问题讨论】:

  • 这是一个非常具体的问题。它不仅仅是扁平化一个数组,它是将数据规范化为一个只有你知道它看起来正确的形式。因此,问题是:定义目标结构的规则是什么?
  • ... 如果一个人坚持 OP 的要求 - 我只需要具有浅键值的对象 - 一个人最终会得到{ "type": "string" } 的列表,因为这是唯一的浅子结构; { "key":"userId", "value": { "type": "string" } } 已经太复杂了。或者浅键值是什么意思?
  • 我的意思是所有具有类型的对象,我的问题是我想验证类型,它们可以是原始类型,如字符串、数字、数组或对象,也可以是用户定义的类型,所以我需要找到它们,然后验证它们。 @PeterSeliger
  • request 和 response 在提供的数据结构的第一层也具有type,但不是预期结果的示例数据的一部分。
  • 是的,这就是问题所在,正如我在问题中所说,JSON 可能是不规则的。包含对象和数组,我需要验证具有“类型”字段的对象

标签: javascript json recursion flatten


【解决方案1】:

下一个提供的方法递归遍历任何给定数据结构的属性键列表,同时寻找与需要提供的另一个键的匹配项。

如果匹配键,相关/引用(子)数据结构将通过额外提供的列表收集。

如果任何(子)数据结构是一个数组,它的每个数据项也将被递归处理。

如果任何(子)数据结构不是字符串类型,该过程将开始一个新的递归,如本文开头所述。

var data = {
	"name": "getPost",
	"request": {
		"type": "object",
		"fields": [{
			"key": "id",
			"value": {
				"type": "string"
			}
		}]
	},
	"response": {
		"type": "object",
		"fields": [{
			"key": "post",
			"value": {
				"type": "object",
				"fields": [{
					"key": "id",
					"value": {
						"type": "string"
					}
				}, {
					"key": "title",
					"value": {
						"type": "string"
					}
				}, {
					"key": "content",
					"value": {
						"type": "string"
					}
				}, {
					"key": "userId",
					"value": {
						"type": "string"
					}
				}]
			}
		}]
	},
	"error": []
};


function collectListOfAllSubTypeDataRecursivelyByKey(collector, key) {
  var
    itemKey = collector.key,
    data    = collector.data,
    list    = collector.list;

  if (Array.isArray(data)) {
    data.forEach(function (dataItem) {

      collector.list = list.concat(Object.keys(dataItem).reduce(collectListOfAllSubTypeDataRecursivelyByKey, {

        key:  itemKey,
        data: dataItem,
        list: []

      }).list);
    })
  } else {
    if (key === itemKey) {

      list.push(data);
    }
    if (typeof (data = data[key]) !== 'string') {

      collector.list = list.concat(Object.keys(data).reduce(collectListOfAllSubTypeDataRecursivelyByKey, {

        key:  itemKey,
        data: data,
        list: []

      }).list);
    }

  }
  return collector;
}


var subTypeList = Object.keys(data).reduce(collectListOfAllSubTypeDataRecursivelyByKey, {

  key:  'type',
  data: data,
  list: []

}).list;


subTypeList.forEach(function (type) {
  console.log('type : ', type);
});
// console.log('subTypeList : ', subTypeList);
.as-console-wrapper { max-height: 100%!important; top: 0; }

对于 OP 提供的已处理数据结构,将有一个列表引用 8 项 sup- 和 sub- 数据结构,每个都具有 type 属性,因为它是要求的。因此反映了这 8 个项目的扁平化列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 2016-08-16
    • 2020-12-22
    • 2020-10-06
    • 1970-01-01
    • 2020-06-23
    相关资源
    最近更新 更多