Pandas и JSON

JSON удобен для логов с веба и MQTT-сообщений ESP32. В Pandas есть пара функций read_json/to_json, а для вложенных структур — pd.json_normalize, который разворачивает иерархию в плоскую таблицу.

Когда использовать

  • Логи REST API (например, отчёты с Home Assistant).

  • MQTT-сообщения, сохранённые построчно в файл.

  • Конфиги устройств, которые нужно сравнить таблично.

Пример 1. Простой JSON массив

data.json:

[{"sensor":"A","value":22.1},{"sensor":"B","value":35.4}]
import pandas as pd

df = pd.read_json("data.json")
print(df)

Output:

  sensor  value
0      A   22.1
1      B   35.4

Пример 2. JSON Lines

Каждая строка — отдельный объект (типично для MQTT-логов):

{"t":0,"v":22.1}
{"t":1,"v":22.3}
import pandas as pd

df = pd.read_json("log.jsonl", lines=True)
print(df)

Output:

   t     v
0  0  22.1
1  1  22.3

Пример 3. Запись JSON

import pandas as pd

df = pd.DataFrame({"a": [1, 2], "b": [3, 4]})
df.to_json("out.json", orient="records", indent=2)

Файл out.json:

[
  {"a":1,"b":3},
  {"a":2,"b":4}
]

Параметр orient="records" даёт привычный массив объектов.

Пример 4. Нормализация вложенных полей

import pandas as pd

payload = [
    {"device": "bot1", "stat": {"battery": 3.7, "temp": 28}},
    {"device": "bot2", "stat": {"battery": 3.9, "temp": 30}},
]
df = pd.json_normalize(payload)
print(df)

Output:

  device  stat.battery  stat.temp
0   bot1           3.7         28
1   bot2           3.9         30

Вложенный объект stat развернулся в два отдельных столбца.

Пример 5. Списки внутри

import pandas as pd

payload = [
    {"id": 1, "tags": ["temp", "hum"]},
    {"id": 2, "tags": ["temp"]},
]
df = pd.json_normalize(payload, record_path="tags", meta=["id"])
print(df)

Output:

      0  id
0  temp   1
1   hum   1
2  temp   2

Пример 6. JSON из URL

import pandas as pd

df = pd.read_json("https://example.com/api/log.json")
print(df.head())

Pandas сам скачает и разберёт ответ.

Пример 7. orient при записи

import pandas as pd

df = pd.DataFrame({"a": [1, 2]})
print(df.to_json(orient="split"))
print(df.to_json(orient="records"))

Output:

{"columns":["a"],"index":[0,1],"data":[[1],[2]]}
[{"a":1},{"a":2}]

Подводные камни

  • read_json падает на «битом» JSON — лучше открывать .jsonl с lines=True.

  • json_normalize теряет глубокие списки, если не передан record_path.

  • Большие JSON лучше парсить потоково через ijson и затем кормить в Pandas.

См. также

Примечание

Лицензия и источники

Техническое описание адаптировано из официальной документации Pandas (https://pandas.pydata.org/docs/), BSD-3-Clause License. Перевод на русский, примеры и пояснения — © AlashEd Wiki.