Как извлечь несколько значений json из вложенного ответа json, используя python - PullRequest
0 голосов
/ 04 мая 2020

Мой тестовый URL возвращается ниже json Ответ: a = {"version": "1.3.0", "services": [{"version": "1.0.0", "serviceGun": "com.xx .version.1 "," description ":" test service "," links ": [{" rel ": "abilities", "href": "/ abc / test", "hints": [{"method": "get"}]

    },
{
    "version": "1.0.0",
    "serviceGun": "com.xx.abx.version.1",
    "description": "mode",
    "links": [ 
    {
        "rel": "mediaConfiguration",
        "href": "/abc/rest",
        "hints": [ 
        {
            "method": "get"

        },
        {
            "method": "put"
        } ]

    },
    {
        "rel": "modeConfiguration",
        "href": "/abc/mode",
        "hints": [ 
        {
            "method": "get"

        },
        {
            "method": "put"
        } ]

    },

{
    "version": "1.0.0",
    "serviceGun": "com.xx.abc.version.1",
    "description": "controlPanel",
    "links": [ 
    {
        "rel": "configuration",
        "href": "/abc/controlPanel",
        "hints": [ 
        {
            "method": "get"

        },
        {
            "method": "put"
        } ]

    },
    {
        "rel": "state",
        "href": "/abc/awc",
        "state": "unavailable",
        "stateReason": "inactivated",
        "hints": [ 
        {
            "method": "get"
        } ]
    } ]

},
 ]

}

С помощью функции ниже я могу получить одно значение из json (например, href, rel et c). Но я хочу, чтобы функция возвращала список, в котором есть все «href» с поддерживающими методами в «hints» для каждого href. Например: [(href1, hints1), (href1, hints1), (href1, hints1)]

Ожидаемый результат: [('/ abc / test', ['get', 'put']), ('/abc/rest',['get','put']),...]

def extract_values ​​(obj, key): "" "Извлечь все значения указанного ключа из вложенного JSON. "" "arr = []

def extract(obj, arr, key):
    """Recursively search for values of key in JSON tree."""
    if isinstance(obj, dict):
        for k, v in obj.items():
            if isinstance(v, (dict, list)):
                extract(v, arr, key)
            elif k == key:
                arr.append(v)
    elif isinstance(obj, list):
        for item in obj:
            extract(item, arr, key)
    return arr

results = extract(obj, arr, key)
return results

Run: test_ref = extract_values ​​(a, 'href') print test_ref Вывод: ['/ abc / test', '/ abc / rest', ' , '/ abc / mode', '/ abc / controlPanel', 'abc / aw c']

Ожидаемый результат: [('/ abc / test', ['get', 'put' ]), ( '/ ABC / отдых', [ 'получить', 'ставить']), ...]

1 Ответ

1 голос
/ 04 мая 2020

Я думаю, что ваша рекурсия пытается решить проблему, которая не существует. Ваш JSON имеет иерархическую структуру, которая хорошо видна.

  1. a['services'] - список услуг
  2. a['services'][i]['links'] - список ссылок i th службы
  3. a['services'][i]['links'][j]['href'] - URL-адрес j th ссылка i th службы

Так что моя функция выглядела бы так:

def parse_links_and_methods(json_result):
    for service in json_result['services']:
        for link in service['links']:
            for hint in link['hints']:
                if 'method' in hint:
                    yield link['href'], hint['method']

По сути, это всего лишь одно огромное понимание списка. Вы будете использовать его как:

print list(parse_links_and_methods(a))

и получите [('/abc/test', 'get'), ('/abc/rest', 'get'), ('/abc/rest', 'put'), ('/abc/mode', 'get'), ('/abc/mode', 'put'), ...]

РЕДАКТИРОВАТЬ Я неправильно понял ваш ожидаемый результат. Чтобы все было так, как вы хотите, используйте

def parse_links_and_methods(json_result):
    for service in json_result['services']:
        for link in service['links']:
            methods = [hint['method'] for hint in link['hints']
                       if 'method' in hint]
            yield link['href'], methods
...