【发布时间】:2021-12-22 23:38:27
【问题描述】:
我正在尝试找到一种方法来添加/删除一个或多个 JSON 对象中的一个或多个元素,给定这些元素的父对象键,而不管对象的架构定义如何。
让我们举个例子。 假设我们有以下 JSON 对象:
{
"field1": "",
"field2": "",
"list1": [
{
"list1_field1": "",
"list1_obj1": {
"list1_obj1_field1": "",
},
"list1_field2": "",
},
{
"list1_field1": "",
"list1_obj1": {
"list1_obj1_field1": "",
},
"list1_field2": "",
"list1_field3": "",
"list1_sublist1": [
{
"list1_sublist1_field1": ""
}
]
}
]
}
现在,假设我想在“list1”的所有元素中的“list1_obj1”对象中添加一个新字段。然后,键将是“list1”和“list1_obj1”,新字段将是,例如,“list1_obj1_field2”。 p>
总而言之,在输入键“list1”和“list1_obj1”中,我想在这个嵌套级别添加或删除一个新字段,但是不考虑 JSON 对象的架构。
当然,假设JSON文件中存在“list1”和“list1_obj1”,如果去掉,“list1_obj1_field2”也存在。
现在,我正在努力解决的最大问题是考虑嵌套对象列表。 如果我不考虑这个限制,我可以实现类似以下线程12 中的解决方案。
然后,为了实现这一目标,我设想了一个类似以下的解决方案:
# Remove item from the json object
# Suppose the json object is stored in a variable called "json_object"
keys = "list1.list1_obj1.list1_obj1_field2".split(".")
item = json_object
for i,key in enumerate(keys):
if isinstance(item,dict):
print("it's a dict")
if key in item.keys():
print(item)
if i == len(keys)-1:
# last item, so we can remove it
else:
item = item[key]
else:
print("it's a list")
# loop on the list and for each element remove the item
如果嵌套项目是一个列表,我认为我应该对其进行迭代,并为每个元素找到要删除的正确项目。但是,我发现此解决方案效率低下。 另外,我试图找出一种使函数递归的方法,但没有成功。
任何提示将不胜感激。
非常感谢
编辑 1:
我设法实现了第一个递归版本。
def remove_element(obj, keys, current_key=0):
"""
obj: the item passed in the function. At the beginning it is the entire json object
keys: list that represents the complete key path from the root to the interested field
current_key: index which points to keys list elements
"""
if isinstance(obj, dict):
for k in obj.keys():
if k == keys[current_key]:
if isinstance(obj[k], dict):
obj[k] = remove_element(obj[k], keys, current_key+1)
elif isinstance(obj[k], list):
for i in range(len(obj[k])):
obj[k][i] = remove_element(obj[k][i],keys, current_key+1)
else:
obj[k] = ""
return obj
目前,该函数不会删除所需的字段,而是仅将其设置为“”,因为如果我尝试删除它,我会得到 RuntimeError: dictionary changed size during iteration(删除 obj[k])。
改进之处在于,现在可以在不考虑架构的情况下访问字段。 但是,仍然无法删除它,并且只能访问没有子项的字段(不是列表或字典的所有内容)。
【问题讨论】: