Sha*_*ash 9 python json dictionary
我有一个标准的嵌套json文件,如下所示:它们是多层嵌套的,我必须通过创建新对象来消除所有嵌套.
嵌套的json文件.
{
"persons": [{
"id": "f4d322fa8f552",
"address": {
"building": "710",
"coord": "[123, 465]",
"street": "Avenue Road",
"zipcode": "12345"
},
"cuisine": "Chinese",
"grades": [{
"date": "2013-03-03T00:00:00.000Z",
"grade": "B",
"score": {
"x": 3,
"y": 2
}
}, {
"date": "2012-11-23T00:00:00.000Z",
"grade": "C",
"score": {
"x": 1,
"y": 22
}
}],
"name": "Shash"
}]
}
Run Code Online (Sandbox Code Playgroud)
需要创建的新对象
persons
[
{
"id": "f4d322fa8f552",
"cuisine": "Chinese",
"name": "Shash"
}
]
persons_address
[
{
"id": "f4d322fa8f552",
"building": "710",
"coord": "[123, 465]",
"street": "Avenue Road",
"zipcode": "12345"
}
]
persons_grade
[
{
"id": "f4d322fa8f552",
"__index": "0",
"date": "2013-03-03T00:00:00.000Z",
"grade": "B"
},
{
"id": "f4d322fa8f552",
"__index": "1",
"date": "2012-11-23T00:00:00.000Z",
"grade": "C"
},
]
persons_grade_score
[
{
"id": "f4d322fa8f552",
"__index": "0",
"x": "3",
"y": "2"
},
{
"id": "f4d322fa8f552",
"__index": "1",
"x": "1",
"y": "22"
},
]
Run Code Online (Sandbox Code Playgroud)
我的方法:我使用了一个normalize函数将所有列表都变成了dicts.添加了另一个可以添加id到所有嵌套dicts的函数.
现在我无法遍历每个级别并创建新对象.有没有办法达到这个目的.
创建新对象后的整个想法我们可以将其加载到数据库中.
这是一个通用的解决方案,可以满足您的需求.它使用的概念是递归循环遍历顶级"人物"字典的所有值.根据它找到的每个值的类型,它继续进行.
因此,对于它在每个字典中找到的所有非字典/非列表,它将它们放入您需要的顶级对象中.
或者如果它找到字典或列表,它会递归地再次执行相同的操作,找到更多非字典/非列表或列表或字典.
同样使用collections.defaultdict可以让我们轻松地将每个键的未知数量的列表填充到字典中,这样我们就可以获得所需的4个顶级对象.
from collections import defaultdict
class DictFlattener(object):
def __init__(self, object_id_key, object_name):
"""Constructor.
:param object_id_key: String key that identifies each base object
:param object_name: String name given to the base object in data.
"""
self._object_id_key = object_id_key
self._object_name = object_name
# Store each of the top-level results lists.
self._collected_results = None
def parse(self, data):
"""Parse the given nested dictionary data into separate lists.
Each nested dictionary is transformed into its own list of objects,
associated with the original object via the object id.
:param data: Dictionary of data to parse.
:returns: Single dictionary containing the resulting lists of
objects, where each key is the object name combined with the
list name via an underscore.
"""
self._collected_results = defaultdict(list)
for value_to_parse in data[self._object_name]:
object_id = value_to_parse[self._object_id_key]
parsed_object = {}
for key, value in value_to_parse.items():
sub_object_name = self._object_name + "_" + key
parsed_value = self._parse_value(
value,
object_id,
sub_object_name,
)
if parsed_value:
parsed_object[key] = parsed_value
self._collected_results[self._object_name].append(parsed_object)
return self._collected_results
def _parse_value(self, value_to_parse, object_id, current_object_name, index=None):
"""Parse some value of an unknown type.
If it's a list or a dict, keep parsing, otherwise return it as-is.
:param value_to_parse: Value to parse
:param object_id: String id of the current top object being parsed.
:param current_object_name: Name of the current level being parsed.
:returns: None if value_to_parse is a dict or a list, otherwise returns
value_to_parse.
"""
if isinstance(value_to_parse, dict):
self._parse_dict(
value_to_parse,
object_id,
current_object_name,
index=index,
)
elif isinstance(value_to_parse, list):
self._parse_list(
value_to_parse,
object_id,
current_object_name,
)
else:
return value_to_parse
def _parse_dict(self, dict_to_parse, object_id, current_object_name,
index=None):
"""Parse some value of a dict type and store it in self._collected_results.
:param dict_to_parse: Dict to parse
:param object_id: String id of the current top object being parsed.
:param current_object_name: Name of the current level being parsed.
"""
parsed_dict = {
self._object_id_key: object_id,
}
if index is not None:
parsed_dict["__index"] = index
for key, value in dict_to_parse.items():
sub_object_name = current_object_name + "_" + key
parsed_value = self._parse_value(
value,
object_id,
sub_object_name,
index=index,
)
if parsed_value:
parsed_dict[key] = value
self._collected_results[current_object_name].append(parsed_dict)
def _parse_list(self, list_to_parse, object_id, current_object_name):
"""Parse some value of a list type and store it in self._collected_results.
:param list_to_parse: Dict to parse
:param object_id: String id of the current top object being parsed.
:param current_object_name: Name of the current level being parsed.
"""
for index, sub_dict in enumerate(list_to_parse):
self._parse_value(
sub_dict,
object_id,
current_object_name,
index=index,
)
Run Code Online (Sandbox Code Playgroud)
然后使用它:
parser = DictFlattener("id", "persons")
results = parser.parse(test_data)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
203 次 |
| 最近记录: |