代码之家  ›  专栏  ›  技术社区  ›  Outcast

获取嵌套字典和列表字典中父键和索引的“路径”

  •  1
  • Outcast  · 技术社区  · 6 年前

    我从Google助手那里收到了一个很大的JSON,我想从中检索一些具体的细节。JSON如下:

    {
        "responseId": "************************",
        "queryResult": {
            "queryText": "actions_intent_DELIVERY_ADDRESS",
            "action": "delivery",
            "parameters": {},
            "allRequiredParamsPresent": true,
            "fulfillmentMessages": [
                {
                    "text": {
                        "text": [
                            ""
                        ]
                    }
                }
            ],
            "outputContexts": [
                {
                    "name": "************************/agent/sessions/1527070836044/contexts/actions_capability_screen_output"
                },
                {
                    "name": "************************/agent/sessions/1527070836044/contexts/more",
                    "parameters": {
                        "polar": "no",
                        "polar.original": "No",
                        "cardinal": 2,
                        "cardinal.original": "2"
                    }
                },
                {
                    "name": "************************/agent/sessions/1527070836044/contexts/actions_capability_audio_output"
                },
                {
                    "name": "************************/agent/sessions/1527070836044/contexts/actions_capability_media_response_audio"
                },
                {
                    "name": "************************/agent/sessions/1527070836044/contexts/actions_intent_delivery_address",
                    "parameters": {
                        "DELIVERY_ADDRESS_VALUE": {
                            "userDecision": "ACCEPTED",
                            "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue",
                            "location": {
                                "postalAddress": {
                                    "regionCode": "US",
                                    "recipients": [
                                        "Amazon"
                                    ],
                                    "postalCode": "NY 10001",
                                    "locality": "New York",
                                    "addressLines": [
                                        "450 West 33rd Street"
                                    ]
                                },
                                "phoneNumber": "+1 206-266-2992"
                            }
                        }
                    }
                },
                {
                    "name": "************************/agent/sessions/1527070836044/contexts/actions_capability_web_browser"
                }
            ],
            "intent": {
                "name": "************************/agent/intents/86fb2293-7ae9-4bed-adeb-6dfe8797e5ff",
                "displayName": "Delivery"
            },
            "intentDetectionConfidence": 1,
            "diagnosticInfo": {},
            "languageCode": "en-gb"
        },
        "originalDetectIntentRequest": {
            "source": "google",
            "version": "2",
            "payload": {
                "isInSandbox": true,
                "surface": {
                    "capabilities": [
                        {
                            "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
                        },
                        {
                            "name": "actions.capability.SCREEN_OUTPUT"
                        },
                        {
                            "name": "actions.capability.AUDIO_OUTPUT"
                        },
                        {
                            "name": "actions.capability.WEB_BROWSER"
                        }
                    ]
                },
                "inputs": [
                    {
                        "rawInputs": [
                            {
                                "query": "450 West 33rd Street"
                            }
                        ],
                        "arguments": [
                            {
                                "extension": {
                                    "userDecision": "ACCEPTED",
                                    "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValue",
                                    "location": {
                                        "postalAddress": {
                                            "regionCode": "US",
                                            "recipients": [
                                                "Amazon"
                                            ],
                                            "postalCode": "NY 10001",
                                            "locality": "New York",
                                            "addressLines": [
                                                "450 West 33rd Street"
                                            ]
                                        },
                                        "phoneNumber": "+1 206-266-2992"
                                    }
                                },
                                "name": "DELIVERY_ADDRESS_VALUE"
                            }
                        ],
                        "intent": "actions.intent.DELIVERY_ADDRESS"
                    }
                ],
                "user": {
                    "lastSeen": "2018-05-23T10:20:25Z",
                    "locale": "en-GB",
                    "userId": "************************"
                },
                "conversation": {
                    "conversationId": "************************",
                    "type": "ACTIVE",
                    "conversationToken": "[\"more\"]"
                },
                "availableSurfaces": [
                    {
                        "capabilities": [
                            {
                                "name": "actions.capability.SCREEN_OUTPUT"
                            },
                            {
                                "name": "actions.capability.AUDIO_OUTPUT"
                            },
                            {
                                "name": "actions.capability.WEB_BROWSER"
                            }
                        ]
                    }
                ]
            }
        },
        "session": "************************/agent/sessions/1527070836044"
    }
    

    这个大型JSON将用户的交付地址详细信息(这里我以Amazon的NY位置详细信息为例)返回到我的后端。因此,我想取回 location 字典,在这个大型JSON的末尾。这个 位置 详细信息也出现在这个JSON的开头,但是我想特别检索第二个 位置 字典,在这个大型JSON的末尾。

    因此,我必须自己阅读这个JSON,并手动测试 位置 在这个大型JSON中使用字典最终发现我必须编写以下行来检索第二行 位置 词典:

    location = json['originalDetectIntentRequest']['payload']['inputs'][0]['arguments'][0]['extension']['location']
    

    因此,我的问题是:是否有任何简洁的方法来自动检索第二个父键和索引的“路径” 位置 在这个大型JSON中有字典吗?

    因此,我期望函数输出的一般格式,该函数对所有出现的 位置 任何JSON中的字典如下:

    [["path" of first `location` dictionary], ["path" of second `location` dictionary], ["path" of third `location` dictionary], ...]
    

    上面的JSON在哪里?

    [["path" of first `location` dictionary], ["path" of second `location` dictionary]]
    

    因为有两次 位置 字典

    ["path" of second `location` dictionary] = ['originalDetectIntentRequest', 'payload', 'inputs', 0, 'arguments', 0, 'extension', 'location']
    

    我脑子里有堆溢出的相关帖子( Python--Finding Parent Keys for a specific value in a nested dictionary )但我不确定这些是否完全适用于我的问题,因为它们适用于嵌套字典中的父键,而这里我讨论的是带有嵌套字典和列表的字典中的父键和索引。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Shivam Singh    6 年前

    我用递归搜索解决了这个问题

    # result and path should be outside of the scope of find_path to persist values during recursive calls to the function
    result = []
    path = []
    from copy import copy
    
    # i is the index of the list that dict_obj is part of
    def find_path(dict_obj,key,i=None):
        for k,v in dict_obj.items():
            # add key to path
            path.append(k)
            if isinstance(v,dict):
                # continue searching
                find_path(v, key,i)
            if isinstance(v,list):
                # search through list of dictionaries
                for i,item in enumerate(v):
                    # add the index of list that item dict is part of, to path
                    path.append(i)
                    if isinstance(item,dict):
                        # continue searching in item dict
                        find_path(item, key,i)
                    # if reached here, the last added index was incorrect, so removed
                    path.pop()
            if k == key:
                # add path to our result
                result.append(copy(path))
            # remove the key added in the first line
            if path != []:
                path.pop()
    
    # default starting index is set to None
    find_path(di,"location")
    print(result)
    # [['queryResult', 'outputContexts', 4, 'parameters', 'DELIVERY_ADDRESS_VALUE', 'location'], ['originalDetectIntentRequest', 'payload', 'inputs', 0, 'arguments', 0, 'extension', 'location']]