Получить «путь» родительских ключей и индексов в словаре вложенных словарей и списков - PullRequest
0 голосов
/ 23 мая 2018

Я получаю большой json из Google Assistant и хочу получить из него некоторые конкретные сведения.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 в Нью-Йорке).Поэтому я хочу получить словарь location, который находится в конце этого большого json.Детали location появляются также в начале этого json, но я хочу получить именно второй словарь location, который находится в конце этого большого json.

По этой причине мне пришлось прочитатьсам этот json и вручную протестировал некоторые возможные «пути» словаря location в этом большом json, чтобы наконец выяснить, что мне пришлось написать следующую строку, чтобы получить второй location словарь:

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

Поэтому мой вопрос заключается в следующем: есть ли какой-нибудь краткий способ автоматического получения «пути» родительских ключей и индексов второго location словаря в этом большом json?

Следовательно, я ожидаю, что общий формат вывода функции, которая делает это для всех вхождений словаря location в любом 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]]

, так как есть два вхождения словаря location с

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

У меня естьна мой взгляд, соответствующие сообщения о StackOverflow ( Python - Поиск родительских ключей для определенного значения во вложенном словаре ), но я не уверен, что они относятся именно к моей проблеме, поскольку они относятся к родительским ключам во вложенных словаряхтогда как здесь я говорю о родительских ключах и индексах в словаре с вложенными словарями и списками.

1 Ответ

0 голосов
/ 23 мая 2018

Я решил это с помощью рекурсивного поиска

# 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']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...