Как обрабатывать вложенный JSON?

У меня проблема. У меня есть вложенный файл JSON:

json_data = '''
{
    "appVersion": "",
    "device": {
        "model": ""
    },
    "bef": {
        "catalog": ""
    },
    "data": [
        {
            "timestamp": "",
            "label": "",
            "category": ""
        }
    ]
}

Я хотел бы извлечь все данные, и если они вложены, я бы хотел, чтобы они были разделены знаком _. Я попытался нормализовать вложенный файл JSON. Для этого я использую json_normalise. К сожалению, желаемый результат — это не то, что я хочу и что мне нужно. Более того, я хочу, чтобы вложенных значений могло быть любое количество, поэтому я попытался решить эту проблему с помощью цикла.

Как я могу получить желаемый результат?

import pandas as pd
import json

json_data = '''
{
    "appVersion": "0.0.3",
    "device": {
        "model": "Lenovo"
    },
    "bef": {
        "catalog": "Manual"
    },
    "data": [
        {
            "timestamp": "2024-04-24 12:08:02.415077",
            "label": "zuf",
            "category": "50"
        }
    ]
}
'''
parsed_json = json.loads(json_data)

def extract_metadata(json_data):
    metadata = {}
    for key, value in json_data.items():
        if isinstance(value, dict):
            for k, v in value.items():
                metadata[f'{key}_{k}'] = v
        else:
            metadata[key] = value
    return metadata

meta_data = extract_metadata(parsed_json)
df_main = pd.json_normalize(parsed_json['data'], sep='_')
df_meta = pd.DataFrame([meta_data])
df = pd.concat([df_main, df_meta], axis=1)


print(df)

Что я имею

                    timestamp label category appVersion device_model  \
0  2024-04-24 12:08:02.415077   zuf       50      0.0.3       Lenovo   

  bef_catalog                                               data  
0     Manual  [{'timestamp': '2024-04-24 12:08:02.415077', '...  

Что я хочу

appVersion  device_model    bef_catalog data_timestamp          data_label  data_category
0.0.3       Lenovo          Manual      2024-04-24 12:08:02.415 zuf         50

Отвечает ли это на ваш вопрос? Как сгладить многоуровневый/вложенный JSON?

Abdul Aziz Barkat 29.04.2024 10:22

@AbdulAzizBarkat спасибо за ваш комментарий. К сожалению, реализация не соответствует желаемому результату. Отображаются только три поля вывода.

Test 29.04.2024 10:31
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
102
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

import pandas as pd
import json

def flatten_json(json_obj, parent_key='', sep='_'):
items = {}
for k, v in json_obj.items():
    new_key = parent_key + sep + k if parent_key else k
    if isinstance(v, dict):
        items.update(flatten_json(v, new_key, sep=sep))
    elif isinstance(v, list):
        for i, item in enumerate(v):
            items.update(flatten_json(item, f"{new_key}{sep}{i}", sep=sep))
    else:
        items[new_key] = v
return items



#Your JSON data


  json_data = '''
{
   "appVersion": "0.0.3",
   "device": {
    "model": "Lenovo"
},
"bef": {
    "catalog": "Manual"
},
"data": [
    {
        "timestamp": "2024-04-24 12:08:02.415",
        "label": "zuf",
        "category": 50
    }
]

} '''

# Parse the JSON data
 parsed_data = json.loads(json_data)

 # Flatten the JSON data
 flattened_data = flatten_json(parsed_data)

   # Convert flattened data to DataFrame
 df = pd.DataFrame(flattened_data, index=[0])

   print(df)

Вы можете сначала сгладить свой словарь следующим образом:

def flatten_dict(d: dict, pre=''):
    new_d = {}
    for key, item in d.items():
        if isinstance(item, dict):
            new_d = {**new_d, **flatten_dict(item, pre=f'{pre}{key}_')}
        elif isinstance(item, list):
            for i, ele in enumerate(item):
                if isinstance(ele, dict):
                    new_d = {**new_d, **flatten_dict(ele, pre=f'{pre}{key}_{i+1}_')}
                else:
                    new_d[f'{pre}{key}_{i+1}'] = ele
        else:
            new_d[f'{pre}{key}'] = item
    return new_d

В вашем коде вы пропустили тип list. Я добавил перечислитель, поскольку в list можно иметь несколько словарей. Если вы уверены, что в списке всегда максимум 1 элемент, вы можете удалить i. Или включите проверку или что-то еще, чтобы проверить, имеет ли список длину 1.

Чтобы преобразовать его в панды:

pd.json_normalize(flatten_dict(parsed_json))

Вывод функции:

flatten_dict(parsed_json)
{'appVersion': '0.0.3',
 'device_model': 'Lenovo',
 'bef_catalog': 'Manual',
 'data_1_timestamp': '2024-04-24 12:08:02.415077',
 'data_1_label': 'zuf',
 'data_1_category': '50'}
Ответ принят как подходящий

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

import pandas as pd
import json
json_data = {your_json_data}
parsed_json = json.loads(json_data)
def extract_metadata(json_data):
    metadata = {}
    for key, value in json_data.items():
        if isinstance(value, dict):
            for k, v in value.items():
                metadata[f'{key}_{k}'] = v
        elif key != 'data':
            metadata[key] = value
    return metadata
meta_data = extract_metadata(parsed_json)
df = pd.DataFrame()
for data in parsed_json['data']:
    data.update(meta_data)
    df = df.append(data, ignore_index=True)
print(df)

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