W3docs

Python JSON

Узнайте, как использовать встроенный модуль json в Python для кодирования, декодирования, чтения и записи данных JSON с примерами и обработкой ошибок.

Встроенный модуль json в Python позволяет преобразовывать объекты Python в JSON-текст и обратно, как правило, с помощью всего двух функций. В этой главе рассматривается всё необходимое: сопоставление типов данных, dumps/loads для строк, dump/load для файлов, форматированный вывод, обработка ошибок и пользовательская сериализация.

Что такое JSON?

JSON (JavaScript Object Notation) — это лёгкий текстовый формат обмена данными. Он удобен для чтения, не зависит от языка программирования и является стандартным форматом для большинства веб-API.

Документ JSON строится из двух структур:

  • Объекты — неупорядоченные наборы пар ключ/значение, заключённые в {}. Ключи всегда являются строками в двойных кавычках.
  • Массивы — упорядоченные последовательности значений, заключённые в [].

Пример JSON-документа:

{
  "name": "John Doe",
  "age": 30,
  "city": "New York",
  "hobbies": ["reading", "traveling", "photography"],
  "active": true,
  "score": null
}

Сопоставление типов Python и JSON

При кодировании или декодировании JSON модуль json в Python преобразует типы согласно следующей таблице:

Тип PythonТип JSONТип Python (после декодирования)
dictobject {}dict
list, tuplearray []list
strstring ""str
int, floatnumberint или float
True / Falsetrue / falsebool
NonenullNone

Обратите внимание: кортежи становятся JSON-массивами и возвращаются как списки Python после декодирования.

Кодирование объектов Python в JSON-строки

json.dumps() (dump-string) сериализует объект Python в строку в формате JSON.

Базовое кодирование

python— editable, runs on the server

Вывод:

{"name": "John Doe", "age": 30, "city": "New York", "hobbies": ["reading", "traveling", "photography"]}

Форматированный вывод с indent и sort_keys

По умолчанию json.dumps() производит компактную однострочную строку. Передайте indent, чтобы получить удобочитаемый вывод, и sort_keys=True, чтобы отсортировать ключи словаря в алфавитном порядке:

import json

person = {
    "name": "John Doe",
    "age": 30,
    "city": "New York",
    "hobbies": ["reading", "traveling", "photography"]
}

print(json.dumps(person, indent=2, sort_keys=True))

Вывод:

{
  "age": 30,
  "city": "New York",
  "hobbies": [
    "reading",
    "traveling",
    "photography"
  ],
  "name": "John Doe"
}

Используйте indent=2 или indent=4 при записи конфигурационных файлов или отладке ответов API — это делает вложенные структуры удобными для чтения.

Декодирование JSON-строк в объекты Python

json.loads() (load-string) разбирает JSON-строку и возвращает эквивалентный объект Python.

Базовое декодирование

python— editable, runs on the server

Вывод:

{'name': 'John Doe', 'age': 30, 'city': 'New York', 'hobbies': ['reading', 'traveling', 'photography']}
<class 'dict'>
John Doe

Декодированное значение является обычным словарём Python, поэтому вы можете обращаться к его ключам через [] или .get(), итерировать с помощью for и т. д.

Обработка некорректного JSON

Если входные данные не являются корректным JSON, json.loads() вызывает исключение json.JSONDecodeError. Всегда перехватывайте его при работе с данными из внешних источников:

import json

raw = '{"name": "Alice", "age":}'   # invalid — missing value

try:
    data = json.loads(raw)
except json.JSONDecodeError as e:
    print(f"Invalid JSON: {e}")

Вывод:

Invalid JSON: Expecting value: line 1 column 24 (char 23)

Смотрите главу Python try/except для полного руководства по обработке исключений.

Работа с вложенным JSON

Объекты JSON могут содержать другие объекты и массивы любой глубины вложенности. Обращайтесь к вложенным значениям с помощью цепочки операторов []:

python— editable, runs on the server

Вывод:

John
traveling

Для глубоко вложенных структур рекомендуется использовать .get() со значением по умолчанию, чтобы избежать KeyError при отсутствующих ключах:

city = person.get("address", {}).get("city", "unknown")

В главе о вложенных словарях рассматриваются паттерны работы с глубоко вложенными словарями Python.

Чтение и запись JSON-файлов

json.dump() записывает данные в файловый объект, а json.load() читает из него. Это файловые аналоги функций dumps/loads.

Запись JSON в файл

import json

data = {"name": "Alice", "scores": [95, 87, 92]}

with open("data.json", "w") as f:
    json.dump(data, f, indent=2)

Это создаёт data.json с форматированным содержимым. Использование with open(...) гарантирует автоматическое закрытие файла — подробности смотрите в главе Работа с файлами в Python.

Чтение JSON из файла

import json

with open("data.json") as f:
    data = json.load(f)

print(data)
print(data["scores"])

Вывод (при условии, что файл был записан выше):

{'name': 'Alice', 'scores': [95, 87, 92]}
[95, 87, 92]

Полный пример с записью и чтением

import json

# Write
config = {"host": "localhost", "port": 5432, "debug": False}
with open("config.json", "w") as f:
    json.dump(config, f, indent=2)

# Read back
with open("config.json") as f:
    loaded = json.load(f)

print(loaded["port"])   # 5432
print(type(loaded["port"]))   # <class 'int'>

Получение JSON из веб-API

В большинстве проектов вам придётся декодировать JSON, поступающий из HTTP-ответов. Популярная библиотека requests упрощает эту задачу:

import requests

response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
response.raise_for_status()   # raises an error for 4xx/5xx responses
data = response.json()        # equivalent to json.loads(response.text)

print(data["title"])
print(data["completed"])

response.json() внутренне вызывает json.loads(). Всегда вызывайте raise_for_status() перед разбором, чтобы неудачный запрос не вернул тело ошибки в тихом режиме.

Пользовательская сериализация с default

Модуль json по умолчанию не может кодировать произвольные объекты Python (например, datetime.date). Передайте вызываемый объект default или пользовательский подкласс JSONEncoder для их обработки:

import json
import datetime

class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.date):
            return obj.isoformat()
        return super().default(obj)

event = {"name": "Conference", "date": datetime.date(2024, 1, 15)}
print(json.dumps(event, cls=DateEncoder))

Вывод:

{"name": "Conference", "date": "2024-01-15"}

Объект date преобразуется в строку ISO 8601 перед сериализацией.

Пользовательская десериализация с object_hook

object_hook вызывается для каждого JSON-объекта (dict) в процессе декодирования. Вы можете использовать его для преобразования данных на лету — например, для конвертации строковых значений в правильные типы Python:

import json

def as_record(d):
    """Convert age field from string to int if present."""
    if "age" in d:
        d["age"] = int(d["age"])
    return d

raw = '{"name": "Bob", "age": "25"}'
person = json.loads(raw, object_hook=as_record)
print(person)
print(type(person["age"]))   # <class 'int'>

Вывод:

{'name': 'Bob', 'age': 25}
<class 'int'>

Краткий справочник

ФункцияНаправлениеИсточник/назначение
json.dumps(obj)Python → JSONвозвращает str
json.loads(s)JSON → Pythonчитает из str
json.dump(obj, f)Python → JSONзаписывает в файл
json.load(f)JSON → Pythonчитает из файла

Ключевые необязательные параметры:

  • indent=2 — форматированный вывод с отступом в 2 пробела
  • sort_keys=True — сортировка ключей словаря в алфавитном порядке
  • cls=MyEncoder — использование пользовательского подкласса JSONEncoder
  • object_hook=fn — преобразование каждого декодированного object dict

Практика

Практика
Which Python function converts a Python dictionary to a JSON-formatted string?
Which Python function converts a Python dictionary to a JSON-formatted string?
Was this page helpful?