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']}

新字典将只包含原始字典中的键。

我建议查看 zipmap and so on as well as list comprehensions and dict comprehensions

等内容