Нормализация вложенного (иерархического) Json в Python

Я извлекаю API, где получаю следующий ответ в формате JSON:

{
  "prod": "Food",
  "id": "F1",
  "item": 
  [
    {
      "prod": "desserts",
      "id": "d1",
      "item": 
      [
        {
          "prod": "chocolates",
          "id": "c1",
          "item": 
          [
            {
              "itemdesc": "Kitkat",
              "id": "kit"
            },
            {
              "itemdesc": "Dairymilk",
              "id": "Dai"
            }
          ]
        },
        {
          "prod": "icecream",
          "id": "id2",
          "item": 
          [
            {
              "itemdesc": "amul",
              "id": "ice"
            }
          ]
        }
      ]
    }
  ]
}

Я хочу преобразовать json в фрейм данных pandas, который будет включать все уровни иерархии и записи детального уровня. У меня есть 7 различных типов пищевых продуктов (например, десерт, пикантные блюда и т. д.), и каждый тип пищевых продуктов, кроме того, имеет детские записи с уровнями иерархии от 3 до максимум 6.

Когда я пытаюсь преобразовать его в фрейм данных, используя pandas.normalize() Я получаю следующий результат

prod    id    item
food    f1    [{"prod": "desserts", "id": "d1", "item": ...]

и когда я пытаюсь указать путь к записи, он дает только один уровень иерархии в соответствии с данным путем к записи.

Но мне нужно сохранить все иерархические записи из ответа json, а именно:

prod             id       item
food             f1       [{"prod": "desserts", "id": "d1", "item": ...]
desserts         d1       [{"prod": "chocolates", "id": "c1", "item": ...]
chocolates       c1       [{"itemdesc": "Kitkat", "id": "kit"...]
NA               kit      Kitkat
NA               Dai      DairyMilk
icecream         id2      [{"itemdesc": "amul", "id": "ice"...]
NA               ice      Amul

Приносим извинения за добавление ответа в формате JSON и вывод в виде изображения. Мне не удалось добавить ответ и вывод в формате JSON внутри вопроса. Заранее спасибо.

Привет, вместо изображений в формате json вы можете использовать jsoneditoronline.org/#, чтобы сохранить json и поделиться там, лучше для описания вашего json будет использовать что-то вроде машинописного текста.

Full-Stack Developer 27.05.2024 11:28
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
2
1
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете сделать это, определив пользовательскую функцию выравнивания и функцию обработки:

import pandas as pd

def flatten_json(y):
    out = []

    def flatten(x, name=''):
        if isinstance(x, dict):
            for a in x:
                flatten(x[a], name + a + '_')
        elif isinstance(x, list):
            i = 0
            for a in x:
                flatten(a, name + str(i) + '_')
                i += 1
        else:
            out.append((name[:-1], x))

    flatten(y)
    return dict(out)


import json

data = {
  "prod": "Food",
  "id": "F1",
  "item": [
    {
      "prod": "desserts",
      "id": "d1",
      "item": [
        {
          "prod": "chocolates",
          "id": "c1",
          "item": [
            {
              "itemdesc": "Kitkat",
              "id": "kit"
            },
            {
              "itemdesc": "Dairymilk",
              "id": "Dai"
            }
          ]
        },
        {
          "prod": "icecream",
          "id": "id2",
          "item": [
            {
              "itemdesc": "amul",
              "id": "ice"
            }
          ]
        }
      ]
    }
  ]
}

def process_json(data, parent_prod=None, parent_id=None):
    rows = []

    current_prod = data.get('prod', 'NA')
    current_id = data.get('id', 'NA')

    rows.append({
        'prod': parent_prod if parent_prod else current_prod,
        'id': current_id,
        'item': json.dumps(data.get('item', [])) if 'item' in data else data.get('itemdesc', 'NA')
    })

    if 'item' in data:
        for item in data['item']:
            rows.extend(process_json(item, current_prod, current_id))

    return rows

flattened_data = process_json(data)

df = pd.DataFrame(flattened_data)

print(df)

что даст тебе

         prod   id                                               item
0        Food   F1  [{"prod": "desserts", "id": "d1", "item": [{"p...
1        Food   d1  [{"prod": "chocolates", "id": "c1", "item": [{...
2    desserts   c1  [{"itemdesc": "Kitkat", "id": "kit"}, {"itemde...
3  chocolates  kit                                             Kitkat
4  chocolates  Dai                                          Dairymilk
5    desserts  id2                [{"itemdesc": "amul", "id": "ice"}]
6    icecream  ice                                               amul

Другие вопросы по теме