За отправку клиенту данных в формате 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 родительского класса.
Результат при обращении в браузере: