Python - 如何将 assign/map 非顺序 JSON 字段添加到字典中
Python - How to assign/map non-sequential JSON fields onto a dict
我有一个 JSON,其中的键并不总是存在,至少不是所有键都在同一位置。例如,“producer”并不总是在 array dict [2] present 上,或者“directors”并不总是在 [1] at JSON 上,这完全取决于我传入函数的 JSON。根据 ['plist']['dict']['key'] 中可用的内容,内容映射到字典 0,1,2,3(studio 除外)...
我如何找到演员、导演、制片人等的对应数组,因为他们并不总是位于相同的数组编号?!
最后,我总是希望能够为正确的字段提取正确的数据,即使 ['plist']['dict']['key'] 有时可能会根据映射的字典而有所不同.
...
def get_plist_meta(element):
if isinstance(element, dict):
return element["string"]
return ", ".join(i["string"] for i in element)
...
### Default map if all fields are present
# 0 = cast
# 1 = directors
# 2 = producers
# 3 = screenwriters
plist_metadata = json.loads(dump_json)
### make fields match the given sequence 0 = cast, 1 = directors etc. ()
if 'cast' in plist_metadata['plist']['dict']['key']:
print("Cast: ", get_plist_meta(plist_metadata['plist']['dict']['array'][0]['dict']))
if 'directors' in plist_metadata['plist']['dict']['key']:
print("Directors: ", get_plist_meta(plist_metadata['plist']['dict']['array'][1]['dict']))
if 'producers' in plist_metadata['plist']['dict']['key']:
print("Producers: ", get_plist_meta(plist_metadata['plist']['dict']['array'][2]['dict']))
if 'screenwriters' in plist_metadata['plist']['dict']['key']:
print("Screenwriters: ", get_plist_meta(plist_metadata['plist']['dict']['array'][3]['dict']))
if 'studio' in plist_metadata['plist']['dict']['key']:
print("Studio: ", plist_metadata['plist']['dict']['string'])
JSON:
{
"plist":{
"@version":"1.0",
"dict":{
"key":[
"cast",
"directors",
"screenwriters",
"studio"
],
"array":[
{
"dict":[
{
"key":"name",
"string":"Martina Piro"
},
{
"key":"name",
"string":"Ralf Stark"
}
]
},
{
"dict":{
"key":"name",
"string":"Franco Camilio"
}
},
{
"dict":{
"key":"name",
"string":"Kai Meisner"
}
}
],
"string":"Helix Films"
}
}
}
JSON也可以在这里得到:https://pastebin.com/JCXRs3Rw
提前致谢
我认为这可以解决您的问题:
import json
dump_json = """{"plist":{"@version":"1.0","dict":{"key":["cast","directors","screenwriters","studio"],"array":[{"dict":[{"key":"name","string":"Martina Piro"},{"key":"name","string":"Ralf Stark"}]},{"dict":{"key":"name","string":"Franco Camilio"}},{"dict":{"key":"name","string":"Kai Meisner"}}],"string":"Helix Films"}}}"""
plist_metadata = json.loads(dump_json)
roles = ['cast', 'directors', 'producers', 'screenwriters'] # all roles
names = {'cast': [], 'directors': [], 'producers': [], 'screenwriters': []} # stores the final output
j = 0 # keeps count of which array entry we are looking at in plist_metadata['plist']['dict']['array']
for x in names.keys(): # cycle through all the possible roles
if x in plist_metadata['plist']['dict']['key']: # if a role exists in the keys, we'll store it in names[role_name]
y = plist_metadata['plist']['dict']['array'][j]['dict'] # keep track of value
if isinstance(plist_metadata['plist']['dict']['array'][j]['dict'], dict): # if its a dict, encase it in a list
y = [plist_metadata['plist']['dict']['array'][j]['dict']]
j += 1 # add to our plist-dict-array index
names[x] = list(map(lambda x: x['string'], y)) # map each of the entries from {"key":"name","string":"Martina Piro"} to just "Martina Piro"
print(names)
def list_names(role_name):
if role_name not in names.keys():
return f'Invalid list request: Role name "{role_name}" not found.'
return f'{role_name.capitalize()}: {", ".join(names[role_name])}'
print(list_names('cast'))
print(list_names('audience'))
输出:
{'cast': ['Martina Piro', 'Ralf Stark'], 'directors': ['Franco Camilio'], 'producers': [], 'screenwriters': ['Kai Meisner']}
Cast: Martina Piro, Ralf Stark
Invalid list request: Role name "audience" not found.
如果您更喜欢 pythonic 解决方案,请试试这个:
# We will use this function to extract the names from the subdicts. We put single items in a new array so the result is consistent, no matter how many names there were.
def get_names(name_dict):
arrayfied = name_dict if isinstance(name_dict, list) else [name_dict]
return [o["string"] for o in arrayfied]
# Make a list of tuples
dict = plist_metadata['plist']['dict']
zipped = zip(dict["key"], dict["array"])
# Get the names from the subdicts and put it into a new dict
result = {k: get_names(v["dict"]) for k, v in zipped}
这会给你一个新的字典,看起来像这样
{'cast': ['Martina Piro', 'Ralf Stark'], 'directors': ['Franco Camilio'], 'screenwriters': ['Kai Meisner']}
新字典将只包含原始字典中的键。
我建议查看 zip
、map
and so on as well as list comprehensions and dict comprehensions、
等内容
我有一个 JSON,其中的键并不总是存在,至少不是所有键都在同一位置。例如,“producer”并不总是在 array dict [2] present 上,或者“directors”并不总是在 [1] at JSON 上,这完全取决于我传入函数的 JSON。根据 ['plist']['dict']['key'] 中可用的内容,内容映射到字典 0,1,2,3(studio 除外)...
我如何找到演员、导演、制片人等的对应数组,因为他们并不总是位于相同的数组编号?! 最后,我总是希望能够为正确的字段提取正确的数据,即使 ['plist']['dict']['key'] 有时可能会根据映射的字典而有所不同.
...
def get_plist_meta(element):
if isinstance(element, dict):
return element["string"]
return ", ".join(i["string"] for i in element)
...
### Default map if all fields are present
# 0 = cast
# 1 = directors
# 2 = producers
# 3 = screenwriters
plist_metadata = json.loads(dump_json)
### make fields match the given sequence 0 = cast, 1 = directors etc. ()
if 'cast' in plist_metadata['plist']['dict']['key']:
print("Cast: ", get_plist_meta(plist_metadata['plist']['dict']['array'][0]['dict']))
if 'directors' in plist_metadata['plist']['dict']['key']:
print("Directors: ", get_plist_meta(plist_metadata['plist']['dict']['array'][1]['dict']))
if 'producers' in plist_metadata['plist']['dict']['key']:
print("Producers: ", get_plist_meta(plist_metadata['plist']['dict']['array'][2]['dict']))
if 'screenwriters' in plist_metadata['plist']['dict']['key']:
print("Screenwriters: ", get_plist_meta(plist_metadata['plist']['dict']['array'][3]['dict']))
if 'studio' in plist_metadata['plist']['dict']['key']:
print("Studio: ", plist_metadata['plist']['dict']['string'])
JSON:
{
"plist":{
"@version":"1.0",
"dict":{
"key":[
"cast",
"directors",
"screenwriters",
"studio"
],
"array":[
{
"dict":[
{
"key":"name",
"string":"Martina Piro"
},
{
"key":"name",
"string":"Ralf Stark"
}
]
},
{
"dict":{
"key":"name",
"string":"Franco Camilio"
}
},
{
"dict":{
"key":"name",
"string":"Kai Meisner"
}
}
],
"string":"Helix Films"
}
}
}
JSON也可以在这里得到:https://pastebin.com/JCXRs3Rw
提前致谢
我认为这可以解决您的问题:
import json
dump_json = """{"plist":{"@version":"1.0","dict":{"key":["cast","directors","screenwriters","studio"],"array":[{"dict":[{"key":"name","string":"Martina Piro"},{"key":"name","string":"Ralf Stark"}]},{"dict":{"key":"name","string":"Franco Camilio"}},{"dict":{"key":"name","string":"Kai Meisner"}}],"string":"Helix Films"}}}"""
plist_metadata = json.loads(dump_json)
roles = ['cast', 'directors', 'producers', 'screenwriters'] # all roles
names = {'cast': [], 'directors': [], 'producers': [], 'screenwriters': []} # stores the final output
j = 0 # keeps count of which array entry we are looking at in plist_metadata['plist']['dict']['array']
for x in names.keys(): # cycle through all the possible roles
if x in plist_metadata['plist']['dict']['key']: # if a role exists in the keys, we'll store it in names[role_name]
y = plist_metadata['plist']['dict']['array'][j]['dict'] # keep track of value
if isinstance(plist_metadata['plist']['dict']['array'][j]['dict'], dict): # if its a dict, encase it in a list
y = [plist_metadata['plist']['dict']['array'][j]['dict']]
j += 1 # add to our plist-dict-array index
names[x] = list(map(lambda x: x['string'], y)) # map each of the entries from {"key":"name","string":"Martina Piro"} to just "Martina Piro"
print(names)
def list_names(role_name):
if role_name not in names.keys():
return f'Invalid list request: Role name "{role_name}" not found.'
return f'{role_name.capitalize()}: {", ".join(names[role_name])}'
print(list_names('cast'))
print(list_names('audience'))
输出:
{'cast': ['Martina Piro', 'Ralf Stark'], 'directors': ['Franco Camilio'], 'producers': [], 'screenwriters': ['Kai Meisner']}
Cast: Martina Piro, Ralf Stark
Invalid list request: Role name "audience" not found.
如果您更喜欢 pythonic 解决方案,请试试这个:
# We will use this function to extract the names from the subdicts. We put single items in a new array so the result is consistent, no matter how many names there were.
def get_names(name_dict):
arrayfied = name_dict if isinstance(name_dict, list) else [name_dict]
return [o["string"] for o in arrayfied]
# Make a list of tuples
dict = plist_metadata['plist']['dict']
zipped = zip(dict["key"], dict["array"])
# Get the names from the subdicts and put it into a new dict
result = {k: get_names(v["dict"]) for k, v in zipped}
这会给你一个新的字典,看起来像这样
{'cast': ['Martina Piro', 'Ralf Stark'], 'directors': ['Franco Camilio'], 'screenwriters': ['Kai Meisner']}
新字典将只包含原始字典中的键。
我建议查看 zip
、map
and so on as well as list comprehensions and dict comprehensions、