За отправку клиенту данных в формате JSON в Django отвечает специальный класс - JsonResponse, который по сути представляет подкласс HttpResponse. Основная особенность JsonResponse состоит в том, что при отправке данных он автоматически устанавливает для заголовка Content-Type (тип содержимого) значение application/json
Его конструктор принимает ряд параметров:
def __init__(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)
data: отправляемые данные
encoder: сериализатор, которые сериализует отправляемые данные в формат JSON. По умолчанию представляет
тип django.core.serializers.json.DjangoJSONEncoder
safe: представляет булевое значение. Если равно False
, то сериализации подлежит любой объект.
Если же равно True
, то отправляемые данные должны представлять тип dict - то есть словарь. По умолчанию равно True
json_dumps_params: словарь аргументов, который передается в функцию json.dumps()
для генерации ответа
Например, отправим какие-нибудь данные в формате JSON. Для этого определим в файле views.py следующий код:
from django.http import JsonResponse def index(request): return JsonResponse({"name": "Tom", "age": 38})
В данном случае отправляется словарь с двумя элементами name и age. И при обращении в браузере к функции index мы увидим эти данные:
По умолчанию JsonResponse сериазует и отправляет только словари. Однако что, если мы хотим отправить объект какого-то своего типа? В этом случае неоьходимо определить класс-сериализатор, который будет содержать логику сериализации объекта в json. Например:
from django.http import JsonResponse from django.core.serializers.json import DjangoJSONEncoder def index(request): bob = Person("Bob", 41) return JsonResponse(bob, safe=False, encoder=PersonEncoder) class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека class PersonEncoder(DjangoJSONEncoder): def default(self, obj): if isinstance(obj, Person): return {"name": obj.name, "age": obj.age} # return obj.__dict__ return super().default(obj)
В данном случае JsonResponse отправляет объект типа Person, у которого определены два атрибута: name и age.
Объект Person не является словарем, поэтому параметр safe
имеет значение False
. Кроме того, параметр encoder
указывает на сериализатор, который будет сериализовать данные в json. В данном случае это класс PersonEncoder.
Класс сериализатора наследуется от django.core.serializers.json.DjangoJSONEncoder
. Он реализует метод
default
, который возвращает сериализованный объект. В частности, в этом методе сначала проверяем, представляет ли параметр объект Person. И если
представляет, то возвращаем словарь из значений атрибутов объекта
return {"name": obj.name, "age": obj.age}
Стоит отметить, что в данном случае мы можем просто возвратить представление объекта в виде словаря
return obj.__dict__
Однако в отдельных ситуациях может потребоваться более тонкая настройка сериализации.
Если же объект не представляет тип Person, то передаем его в реализацию метода default родительского класса.
Результат при обращении в браузере: