合并包含dict&;的两个json文件;使用python将列表转换为单个json?
我正在尝试使用python将两个JSON文件合并成一个JSON 文件1:合并包含dict&;的两个json文件;使用python将列表转换为单个json?,python,json,Python,Json,我正在尝试使用python将两个JSON文件合并成一个JSON 文件1: { "key1": "protocol1", "key2": [ { "name": "user.name", "value": "user@EXAMPLE123.COM" }, { "name": "u
{
"key1": "protocol1",
"key2": [
{
"name": "user.name",
"value": "user@EXAMPLE123.COM"
},
{
"name": "user.shortname",
"value": "user"
},
{
"name": "proxyuser.hosts",
"value": "*"
},
{
"name": "kb.groups",
"value": "hadoop,users,localusers"
},
{
"name": "proxy.groups",
"value": "group1, group2, group3"
},
{
"name": "internal.user.groups",
"value": "group1, group2"
}
]
}
文件2:
{
"key1": "protocol1",
"key2": [
{
"name": "user.name",
"value": "user@EXAMPLE456.COM"
},
{
"name": "user.shortname",
"value": "user"
},
{
"name": "proxyuser.hosts",
"value": "*"
},
{
"name": "kb.groups",
"value": ""
},
{
"name": "proxy.groups",
"value": "group3, group4, group5"
},
{
"name": "internal.groups",
"value": "none"
}
]
}
"key2": [{"name" : "firstname", "value" : "charlie"}]
最终预期结果:
{
"key1": "protocol1",
"key2": [
{
"name": "user.name",
"value": "user@EXAMPLE123.COM, user@EXAMPLE456.COM"
},
{
"name": "user.shortname",
"value": "user"
},
{
"name": "proxyuser.hosts",
"value": "*"
},
{
"name": "kb.groups",
"value": "hadoop,users,localusers"
},
{
"name": "proxy.groups",
"value": "group1, group2, group3, group4, group5"
},
{
"name": "internal.user.groups",
"value": "group1, group2"
},
{
"name": "internal.groups",
"value": "none"
}
]
}
我需要根据以下规则进行合并:
列表(key2)
中的“name”键在两个文件中匹配,则将值连接起来
e、 g
文件1:
"key2": [{"name" : "firstname", "value" : "bob"}]
文件2:
{
"key1": "protocol1",
"key2": [
{
"name": "user.name",
"value": "user@EXAMPLE456.COM"
},
{
"name": "user.shortname",
"value": "user"
},
{
"name": "proxyuser.hosts",
"value": "*"
},
{
"name": "kb.groups",
"value": ""
},
{
"name": "proxy.groups",
"value": "group3, group4, group5"
},
{
"name": "internal.groups",
"value": "none"
}
]
}
"key2": [{"name" : "firstname", "value" : "charlie"}]
最终输出:
"key2": [{"name" : "firstname", "value" : "bob, charlie"}]
- 如果两个文件的“值”中都包含重复的值,则最终结果应仅为值的并集
- 如果任何“value”包含“*”,则最终值应为“*”
- 如果第二个JSON文件中的“name”键在第一个文件中不存在,请将其添加到第一个文件中李>
def merge(a, b):
"merges b into a"
for key in b:
if key in a:# if key is in both a and b
if key == "key1":
pass
elif key == "key2":
for d1, d2 in zip(a[key], b[key]):
for key, value in d1.items():
if value != d2[key]:
a.append({"name": d2[key], "value": d2["value"]})
else:
a[key] = a[key]+ b[key]
else: # if the key is not in dict a , add it to dict a
a.update({key:b[key]})
return a
有人能指出我如何将“name”部分的值与两个文件中的key2列表进行比较,并将“value”中的值串联起来吗?如果没有在新的dict中,只需循环键,如果合并了两个值,则添加它
d1 = {"name" : "firstname", "value" : "bob"}
d2 = {"name" : "firstname", "value" : "charlie"}
d3 = {}
for i in d1:
for j in d2:
if i not in d3:
d3[i] = d1[i]
else:
d3[i] = '{}, {}'.format(d1[i], d2[i])
print(d3)
下面是一个线性时间运行的解决方案,使用字典在给定
名称
键的中快速查找项目。字典b
的key2
列表迭代一次,并根据需要在固定时间内修改a
。集合用于消除重复项和处理星号
def merge(a, b):
lookup = {o['name']: o for o in a['key2']}
for e in a['key2']:
e['value'] = set([x.strip() for x in e['value'].split(",")])
for e in b['key2']:
if e['name'] in lookup:
lookup[e['name']]['value'].update([x.strip() for x in e['value'].split(",")])
else:
e['value'] = set([x.strip() for x in e['value'].split(",")])
a['key2'].append(e)
for e in a['key2']:
if "*" in e['value']:
e['value'] = "*"
else:
e['value'] = ", ".join(sorted(list(e['value'])))
样本输出:
key1:
协议1
关键2:
{'name':'user.name','value':'user@EXAMPLE123.COM, user@EXAMPLE456.COM'}
{'name':'user.shortname','value':'user'}
{'name':'proxyuser.hosts','value':'*'}
{'name':'kb.groups','value':',hadoop,localusers,users'}
{'name':'proxy.groups','value':'group1,group2,group3,group4,group5'}
{'name':'internal.user.groups','value':'group1,group2'}
{'name':'internal.groups','value':'none'}
不能保证a[“key2”]
和b[“key2”]
中元素的顺序相同,因此您应该构建一个从“name”
值到a[“key2”]
中索引的映射,然后浏览b[“key2”
将每个“name”
值与该指令进行比较
代码可以是:
def merge(a, b):
"merges b into a"
for key in b:
if key in a:# if key is in both a and b
if key == "key2":
# build a mapping from names from a[key2] to the member index
akey2 = { d["name"]: i for i,d in enumerate(a[key]) }
for d2 in b[key]: # browse b["key2"]
if d2["name"] in akey2: # a name from a["key2"] matches
a[key][akey2[d2["name"]]]["value"] += ", " + d2["value"]
else:
a[key].append(d2) # when no match
else: # if the key is not in dict a , add it to dict a
a[key] = b[key]
return a
然后,您可以测试它:
a = {"key1": "value1",
"key2": [{"name" : "firstname", "value" : "bob"}]
}
b = {"key1": "value2",
"key2": [{"name" : "firstname", "value" : "charlie"},
{"name" : "foo", "value": "bar"}]
}
merge(a, b)
pprint.pprint(a)
如预期所示:
{'key1': 'value1',
'key2': [{'name': 'firstname', 'value': 'bob, charlie'},
{'name': 'foo', 'value': 'bar'}]}
一旦你读取并反序列化了数据,它就不再与JSON有关了,因此你可以减少你的问题。@Ulrich Eckhardt感谢你指出这一点,但写回第一个文件不会将其序列化吗?@ggorlen:我只是在发布我的答案后才看到你的答案,然后意识到它们是一样的。我把这个放在这里,因为它集成了OP的merge函数中的代码。如果您在回答中这样做,并在评论中ping我,我将删除此项。我们是否可以避免在此处附加重复值(a中已存在值)?@TusharKarkera:是的。将两个value
字符串拆分为多个集合就足够了,将两个集合合并,然后合并结果。懒得去做。。。无论如何,它需要一个精确的值格式规范。我已经添加了输入格式的精确规范,以及如何在我的原始问题编辑中合并它们。如果有什么不清楚的地方,请告诉我。谢谢你的帮助@TusharKarkera:正如我已经说过的,我太懒了,而ggorlen的答案已经包含了我本可以为你做的事情,ggorlen和@Serge Ballesta为你的答案。代码可以很好地比较“name”值,但对于以下情况,需要临时修改:如果“value”:“*”,那么当我们合并相同“name”的值时;理想情况下,它应该只打印一个“*”,但现在它打印“*,*”。我并不是100%地遵循——你是说你希望值
列表仅为唯一项?请用新的要求更新您的问题,我会在有时间时更新我的答案。更新原始问题以更清楚,谢谢!此行不追加值,而是覆盖查找[e['name']['value']=e['value']]
我确实尝试了追加,尽管我面临的一个问题是重复值。因为“value”中可能有两个列表中匹配的值。我尝试使用set()消除重复项,但得到的错误是set不是JSON Serializable我不理解您的更新版本。除了proxy.groups
键外,所有内容都已清除。文件1和文件2都有值group1、group2、group3
。我希望合并的输出是group1、group2、group3
,但不知何故,您正在寻找group1、group2、group3、group4、group5
,这两个组都很奇怪,因为两个组是由蓝色组成的,如果您对数字组扩展感兴趣,我希望出现6个组而不是5个组。请解释一下你是如何实现这一转变的。在此期间,我更新了我的代码,以处理除此edge案例之外的所有问题。