Язык, на котором говорят API
API обмениваются данными в формате JSON — это текст вида {"id": 1, "name": "Ana"}. Модуль json в Python переводит данные в обе стороны: json.dumps превращает данные Python в текст JSON, а json.loads разбирает текст JSON в данные Python.
Никакой слой сопоставления настраивать не нужно: ключи — это имена полей в том виде, в каком они написаны. dataclass задаёт записи фиксированную структуру, а dataclasses.asdict превращает её в обычный словарь, готовый для json.dumps. Если API требует другое написание ключей, переименуйте их вручную.
Из данных Python в JSON
json.dumps выдаёт JSON в одну строку — для машин; json.dumps(..., indent=2) выдаёт читаемый JSON — для людей и логов. Ничего не отбрасывается автоматически: если пустое поле не должно попасть в JSON, удалите его из словаря перед преобразованием.
В одну строку и красиво
У Ana нет email, и вспомогательная функция удаляет пустое поле из её словаря — её JSON остаётся чистым. Полная запись Ben выводится с отступами.
Вывод: полная программа на Python
import json
from dataclasses import dataclass, asdict
@dataclass
class User:
id: int
name: str
email: str = ""
def to_json_dict(user):
data = asdict(user) # ключи — это имена полей в том виде, в каком они написаны
if data["email"] == "":
del data["email"] # удаляем пустое поле вручную
return data
ana = User(id=1, name="Ana")
print(json.dumps(to_json_dict(ana)))
ben = User(id=2, name="Ben", email="ben@example.com")
print(json.dumps(to_json_dict(ben), indent=2))
Из JSON в данные Python
json.loads разбирает JSON в обычные данные Python — словари, списки, строки, числа. Неизвестные ключи не выбрасываются: всё, что есть в JSON, попадает в словарь, а типизированная запись строится только из нужных ей полей. Некорректный JSON вызывает json.JSONDecodeError — перехватывайте эту ошибку: она сигнализирует, что текст вообще не был JSON.
loads и лишний ключ
В JSON есть ключ extra, которого нет в dataclass User, — json.loads сохраняет его в словаре, а dataclass просто берёт два нужных ему поля. Сломанный JSON, напротив, вызывает настоящую ошибку.
Вывод: полная программа на Python
import json
from dataclasses import dataclass
@dataclass
class User:
id: int
name: str
data = '{"id": 7, "name": "Cleo", "extra": "kept"}'
raw = json.loads(data)
print(raw) # неизвестный ключ сохраняется в словаре
user = User(id=raw["id"], name=raw["name"]) # берём нужные поля
print(user)
try:
json.loads('{"id": ')
except json.JSONDecodeError as err:
print("ошибка:", err)
Вложенные данные
Реальные данные API вложены: заказ содержит своего пользователя и список товаров. Dataclass внутри dataclass и списки автоматически превращаются в объекты и массивы JSON — asdict обходит всю структуру.
Заказ с пользователем внутри
Вложенный dataclass User становится вложенным объектом JSON, список товаров — массивом JSON: структура данных Python и есть структура JSON.
Вывод: полная программа на Python
import json
from dataclasses import dataclass, asdict
@dataclass
class User:
id: int
name: str
@dataclass
class Order:
id: int
items: list[str]
user: User
order = Order(id=1042, items=["keyboard", "mouse"], user=User(id=1, name="Ana"))
print(json.dumps(asdict(order), indent=2))