我正在比较两个不同API端点之间的json文件,以查看哪些json记录需要更新,哪些需要创建,哪些需要删除。因此,通过比较两个json文件,我想得到三个json文件,每个操作一个。
两个端点的json的结构如下(但它们对相同的值集使用不同的键;不同的问题):
{
"records": [{
"id": "id-value-here",
"c": {
"d": "eee"
},
"f": {
"l": "last",
"f": "first"
},
"g": ["100", "89", "9831", "09112", "800"]
}, {
…
}]
}
因此json表示为字典列表(还有更多嵌套的列表和字典)。
如果另一个端点json(j2)中存在给定的json端点(j1)id值(“ id” :),则应将该记录添加到j_update。
到目前为止,我有类似的内容,但是我可以看到.values()不起作用,因为它试图对列表进行操作,而不是对所有列出的字典(?)进行操作:
j_update = {r for r in j1['records'] if r['id'] in
j2.values()}
这不会返回错误,但是会使用测试json文件创建一个空集。
看起来像这样应该很简单,但是我想到代表json的列表中的字典会影响嵌套。我是否需要展平j2,还是有一种更简单的字典方法python必须做到这一点?
====编辑j1和j2 ==== 具有相同的结构,使用不同的键;玩具数据
{
"records": [{
"field_5": 2329309841,
"field_12": {
"email": "cmix@etest.com"
},
"field_20": {
"last": "Mixalona",
"first": "Clara"
},
"field_28": ["9002329309999", "9002329309112"],
"field_44": ["1002329309832"]
}, {
"field_5": 2329309831,
"field_12": {
"email": "mherbitz345@test.com"
},
"field_20": {
"last": "Herbitz",
"first": "Michael"
},
"field_28": ["9002329309831", "9002329309112", "8002329309999"],
"field_44": ["1002329309832"]
}, {
"field_5": 2329309855,
"field_12": {
"email": "nkatamaran@test.com"
},
"field_20": {
"first": "Noriss",
"last": "Katamaran"
},
"field_28": ["9002329309111", "8002329309112"],
"field_44": ["1002329309877"]
}]
}
{
"records": [{
"id": 2329309831,
"email": {
"email": "mherbitz345@test.com"
},
"name_primary": {
"last": "Herbitz",
"first": "Michael"
},
"assign": ["8003329309831", "8007329309789"],
"hr_id": ["1002329309877"]
}, {
"id": 2329309884,
"email": {
"email": "yinleeshu@test.com"
},
"name_primary": {
"last": "Lee Shu",
"first": "Yin"
},
"assign": ["8002329309111", "9003329309831", "9002329309111", "8002329309999", "8002329309112"],
"hr_id": ["1002329309832"]
}, {
"id": 23293098338,
"email": {
"email": "amlouis@test.com"
},
"name_primary": {
"last": "Maxwell Louis",
"first": "Albert"
},
"assign": ["8002329309111", "8007329309789", "9003329309831", "8002329309999", "8002329309112"],
"hr_id": ["1002329309877"]
}]
}
答案 0 :(得分:0)
如果您阅读json,它将输出字典。您正在值列表中寻找特定键。
if 'records' in j2:
r = j2['records'][0].get('id', []) # defaults if id does not exist
进行递归搜索比较好,但是我不知道您的数据如何组织起来以便快速提出解决方案。
要给出递归搜索的想法,请考虑以下示例
def resursiveSearch(dictionary, target):
if target in dictionary:
return dictionary[target]
for key, value in dictionary.items():
if isinstance(value, dict):
target = resursiveSearch(value, target)
if target:
return target
a = {'test' : 'b', 'test1' : dict(x = dict(z = 3), y = 2)}
print(resursiveSearch(a, 'z'))
答案 1 :(得分:0)
您尝试过:
var newPostKey = firebaseref.child("user").push().set({name : messageText,prenom:prenomtxt ,email : txtmail}).key;
除了j_update = {r for r in j1['records'] if r['id'] in j2.values()}
问题之外,您还有:
r['id'/'field_5]
>>> list(j2.values())
[[{'id': 2329309831, ...}, ...]]
埋在列表和字典中,因此测试id
始终返回False。
基本解决方案非常简单。
首先,创建一组r['id'] in j2.values()
j2
:
id
然后,重建>>> present_in_j2 = set(record["id"] for record in j2["records"])
的json结构,但不包含j1
中不存在的j1
field_5
:
j2
它可以工作,但是由于>>> {"records":[record for record in j1["records"] if record["field_5"] in present_in_j2]}
{'records': [{'field_5': 2329309831, 'field_12': {'email': 'mherbitz345@test.com'}, 'field_20': {'last': 'Herbitz', 'first': 'Michael'}, 'field_28': ['9002329309831', '9002329309112', '8002329309999'], 'field_44': ['1002329309832']}]}
怪异的键而不能令人满意。让我们尝试将j1
转换为更友好的格式:
j1
此函数着重于字典键:如果转换表中存在键,则def map_keys(json_value, conversion_table):
"""Map the keys of a json value
This is a recursive DFS"""
def map_keys_aux(json_value):
"""Capture the conversion table"""
if isinstance(json_value, list):
return [map_keys_aux(v) for v in json_value]
elif isinstance(json_value, dict):
return {conversion_table.get(k, k):map_keys_aux(v) for k,v in json_value.items()}
else:
return json_value
return map_keys_aux(json_value)
为conversion_table.get(k, k)
。
conversion_table[k]
现在,代码更简洁了,输出对于>>> j1toj2 = {"field_5":"id", "field_12":"email", "field_20":"name_primary", "field_28":"assign", "field_44":"hr_id"}
>>> mapped_j1 = map_keys(j1, j1toj2)
可能更有用:
PUT