Основные функции модуля json: практические примеры

Раздел: Стандартная библиотека Python -> JSON

Основы работы с библиотекой json

Наиболее эффективное решение для базовых операций с JSON в Python - использование функций json.dumps() для сериализации и json.loads() для десериализации.


import json

data = {"name": "Анна", "age": 30, "city": "Москва"}
json_string = json.dumps(data, ensure_ascii=False, indent=2)
print(json_string)

Python 3 json (работа с json в python 3)

{
  "name": "Анна",
  "age": 30,
  "city": "Москва"
}

Json open python (открытие json файла в python)

Параметр ensure_ascii=False сохраняет кириллицу, indent=2 добавляет отступы. Для загрузки строки обратно в объект Python используется json.loads().

Как сериализовать данные с кастомными типами (например, datetime)?

По умолчанию json.dumps() не умеет обрабатывать объекты datetime. Для этого используется параметр default или создается собственный класс, наследующий от json.JSONEncoder.


import json
from datetime import datetime

def custom_serializer(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Object of type {type(obj)} is not JSON serializable")

data = {"now": datetime.now()}
json_str = json.dumps(data, default=custom_serializer, indent=2)
print(json_str)

преобразовать json в словарь python (преобразование json в словарь python)

{
  "now": "2025-04-05T12:34:56.789012"
}

сохранить json python (сохранение json в файл python)

Проблема: Если не указать default, возникнет TypeError: Object of type datetime is not JSON serializable.

Решение: Определить функцию, преобразующую неподдерживаемые типы в строку или другой поддерживаемый формат, и передать её в параметр default.

Как загрузить JSON из файла?

Для чтения JSON из файла используется json.load(), которая принимает файловый объект.


with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)
print(data)

Python json lib (библиотека json в python)

Аналогично, json.dump() записывает данные в файл.


with open("output.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

вложенный json python (вложенный json в python)

Проблема: Если файл содержит некорректный JSON, возникнет json.JSONDecodeError. Также возможны проблемы с кодировкой, если не указать encoding.

Решение: Оборачивать чтение в try-except, указывать явно кодировку utf-8.

Как минимизировать размер JSON (убрать пробелы)?

Для передачи по сети или хранения в компактном виде используют параметр separators.


compact_json = json.dumps(data, separators=(',', ':'))
print(compact_json)

Json lines python (формат json lines в python)

{"name":"Анна","age":30,"city":"Москва"}

Python return json (возврат json из функции python)

Значение (',', ':') убирает все лишние пробелы. Это часто используется во фронтенд-приложениях.

Как отсортировать ключи в JSON?

Параметр sort_keys=True выводит ключи в алфавитном порядке.


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

Как обработать ошибки при разборе JSON?

Используется исключение json.JSONDecodeError, которое наследуется от ValueError.


import json

try:
    data = json.loads('{"invalid": "json"')  # пропущена закрывающая скобка
except json.JSONDecodeError as e:
    print(f"Ошибка разбора: {e}")
Ошибка разбора: Expecting property name enclosed in double quotes: line 1 column 17 (char 16)

Проблема: При разборе стороннего JSON может быть много неожиданных ошибок. Важно не просто игнорировать их, а логировать или обрабатывать соответствующим образом.

Как сериализовать объекты пользовательских классов?

Помимо параметра default, можно создать собственный класс, наследующий от json.JSONEncoder, переопределив метод default().


class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, set):
            return list(obj)
        if isinstance(obj, bytes):
            return obj.decode('utf-8')
        return super().default(obj)

data = {"tags": {"python", "json", "encoding"}, "binary": b"hello"}
json_str = json.dumps(data, cls=MyEncoder, indent=2)
print(json_str)
{
  "tags": ["encoding", "json", "python"],
  "binary": "hello"
}

Проблема: Если не обработать тип, вызовется super().default(), который вызовет TypeError. Необходимо предусмотреть все типы, которые могут встретиться.

Расширенные примеры и нестандартные сценарии

Как выполнить глубокое копирование объекта через JSON?

Пример

import json

original = {"a": [1, 2, {"b": 3}]}
copy = json.loads(json.dumps(original))
original["a"][2]["b"] = 99
print(original)  # {'a': [1, 2, {'b': 99}]}
print(copy)       # {'a': [1, 2, {'b': 3}]}
{'a': [1, 2, {'b': 99}]}
{'a': [1, 2, {'b': 3}]}

Этот метод работает только для типов, представимых в JSON (словари, списки, строки, числа, булевы, None). Для других типов потребуется кастомная сериализация.

Как использовать object_hook для восстановления datetime?

Пример

import json
from datetime import datetime

def datetime_hook(pairs):
    d = dict(pairs)
    for key, value in d.items():
        if isinstance(value, str) and 'T' in value:
            try:
                d[key] = datetime.fromisoformat(value)
            except ValueError:
                pass
    return d

json_str = '{"event": "meeting", "time": "2025-04-05T15:30:00"}'
data = json.loads(json_str, object_hook=datetime_hook)
print(data)
print(type(data["time"]))  # 
{'event': 'meeting', 'time': datetime.datetime(2025, 4, 5, 15, 30)}

Как сериализовать Decimal с сохранением точности?

Пример

from decimal import Decimal
import json

class DecimalEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            return str(obj)
        return super().default(obj)

data = {"price": Decimal('19.99'), "quantity": Decimal('1000')}
json_str = json.dumps(data, cls=DecimalEncoder, indent=2)
print(json_str)
{
  "price": "19.99",
  "quantity": "1000"
}

При загрузке обратно можно написать кастомный парсер для восстановления Decimal.

Как пропустить нестроковые ключи при сериализации?

Пример

import json
data = {1: "one", (1,2): "tuple", "normal": "value"}
json_str = json.dumps(data, skipkeys=True)
print(json_str)
{"normal": "value"}

Параметр skipkeys=True игнорирует ключи, не являющиеся строками, числами или кортежами (кортежи преобразуются в строку).

Как обработать циклические ссылки?

Пример

import json

class Node:
    def __init__(self, value):
        self.value = value
        self.child = None

node = Node(1)
node.child = node

def serializer(obj):
    if isinstance(obj, Node):
        return {"value": obj.value}
    raise TypeError

try:
    json.dumps(node, default=serializer)
except RecursionError:
    print("Рекурсия при сериализации")

Стандартный JSON сериализатор не поддерживает циклические ссылки. Решение - либо избегать их, либо реализовать собственную логику с отслеживанием посещённых объектов.

Как использовать raw_decode для частичного парсинга?

Пример

import json
decoder = json.JSONDecoder()

data = '{"a": 1, "b": 2}{"c": 3}'
while data:
    data = data.lstrip()
    if not data:
        break
    obj, idx = decoder.raw_decode(data)
    print(obj)
    data = data[idx:]
{'a': 1, 'b': 2}
{'c': 3}

Это полезно для потоковой обработки нескольких JSON объектов в одном потоке.

Библиотека json в Python - comments

En
Python json lib (python)