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

时间:2018-05-23 10:57:48

标签: python json dictionary

我从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向我的后端返回用户的交付地址详细信息(这里我以亚马逊的NY位置详细信息为例)。因此,我想检索接近这个大型json末尾的location字典。 location详细信息也出现在此json的开头附近,但我想要专门检索第二个location字典,该字典接近这个大json的末尾。

出于这个原因,我必须自己阅读这个json并手动测试这个大json中location字典的一些可能的“路径”,最后发现我必须编写以下行来检索第二个location字典:

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

因此,我的问题如下:是否有任何简洁的方法可以自动检索此大型json中第二个location字典的父键和索引的“路径”?

因此,我希望在任何json中对location字典的所有出现执行此操作的函数的输出的一般格式如下:

[["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]]

因为{/ 1}}字典有两次出现

location

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

1 个答案:

答案 0 :(得分:1)

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

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