Выборочное сплющивание JSON в Python - PullRequest
0 голосов
/ 16 января 2020

Я извлекаю данные из API, который возвращает нестандартизированные jsons. Это означает, что мне нужно написать пользовательскую функцию для анализа каждого потока данных, поскольку JSON имеет другую структуру вложенных словарей и списков. Вывод, который я хочу получить, представляет собой плоский список, содержащий все соответствующие элементы конечной точки. Я написал функции для некоторых из них, но я пытаюсь создать что-то более общее.

Пример JSON будет иметь вид:

JSON = {
    'metadata' : {
        'meta_param' : 'meta_value',
    },
    'contents' : [
        { 
            'content' : [
                {
                    'attributes' : {
                        'series_name' : 'series_1a',
                    },
                    'data' : {
                        'index' : [0, 1, 2, 3, 4, 5],
                        'values' : [12, 84, 38, 3, 92, 67]
                    },
                },
                {
                    'attributes' : {
                        'series_name' : 'series_2a',
                    },
                    'data' : {
                        'index' : [0, 1, 2, 3, 4, 5],
                        'values' : [42, 73, 48, 20, 19, 61]
                    },
                },
            ],
        },
        {
            'content' : [
                {
                    'attributes' : {
                        'series_name' : 'series_1b',
                    },
                    'data' : {
                        'index' : [0, 1, 2, 3, 4, 5],
                        'values' : [13, 85, 39, 4, 93, 68]
                    },
                },
                {
                    'attributes' : {
                        'series_name' : 'series_2b',
                    },
                    'data' : {
                        'index' : [0, 1, 2, 3, 4, 5],
                        'values' : [43, 74, 49, 21, 20, 62]
                    },
                },
            ],
        },
    ]
}

И я напишу такую ​​функцию, как эта, чтобы преобразовать ее в плоский список

flatlist = []

for contents in JSON['contents']:
    for content in contents['content']:
        flatlist.append(content['data'])

flatlist -> 
[{'index': [0, 1, 2, 3, 4, 5], 'values': [12, 84, 38, 3, 92, 67]},
 {'index': [0, 1, 2, 3, 4, 5], 'values': [42, 73, 48, 20, 19, 61]},
 {'index': [0, 1, 2, 3, 4, 5], 'values': [13, 85, 39, 4, 93, 68]},
 {'index': [0, 1, 2, 3, 4, 5], 'values': [43, 74, 49, 21, 20, 62]}]


Я пытаюсь создать функцию, которая принимает JSON вложенных словарей и списков, а также 'маршрутную карту' для доступа к определенным c элементам внутри нее, а затем возвращает плоский список указанных элементов.

Карта маршрута и ее использование в предыдущем примере будут выглядеть так:

JSON_route = [
    'contents',
    'content',
    'data',
]

flatlist = json_to_flatlist(JSON, JSON_route)

flatlist -> 
[{'index': [0, 1, 2, 3, 4, 5], 'values': [12, 84, 38, 3, 92, 67]},
 {'index': [0, 1, 2, 3, 4, 5], 'values': [42, 73, 48, 20, 19, 61]},
 {'index': [0, 1, 2, 3, 4, 5], 'values': [13, 85, 39, 4, 93, 68]},
 {'index': [0, 1, 2, 3, 4, 5], 'values': [43, 74, 49, 21, 20, 62]}]


Моя ключевая проблема заключается в том, что я не знаю, как программировать преобразовать список JSON_route во вложенные циклы for, необходимые для извлечения данных.

Спасибо за любую помощь!

1 Ответ

2 голосов
/ 16 января 2020
def json_to_flatlist(obj, route):
    if len(route) == 0:
        yield obj
    elif isinstance(obj, list):
        for item in obj:
            yield from json_to_flatlist(item, route)
    else:
        yield from json_to_flatlist(obj[route[0]], route[1:])

JSON_route = [
    'contents',
    'content',
    'data',
]

result = list(json_to_flatlist(JSON, JSON_route))
print(result)

Результат (для ясности добавлены новые строки):

[
{'index': [0, 1, 2, 3, 4, 5], 'values': [12, 84, 38, 3, 92, 67]}, 
{'index': [0, 1, 2, 3, 4, 5], 'values': [42, 73, 48, 20, 19, 61]}, 
{'index': [0, 1, 2, 3, 4, 5], 'values': [13, 85, 39, 4, 93, 68]}, 
{'index': [0, 1, 2, 3, 4, 5], 'values': [43, 74, 49, 21, 20, 62]}
]
...