Computer scienceBackendDjangoViews

JsonResponse object

10 minutes read

Sometimes, we need to send some data from the server to the client in JSON form. JSON is a mandatory form of the data you send or retrieve, especially with APIs. In this topic, let's take a look at how you can use the JsonResponse class in Django to return JSON objects from the view functions.

JSON (JavaScript Object Notation) is a lightweight data-interchange format. The official Internet content type for JSON is application/json. The extension is .json. It has two great advantages: people can easily read it, and machines can easily parse and generate it.

JsonResponse objects

Since 1.7, Django comes with the built-in JsonResponse class. It is a subclass of HttpResponse. Its default content-type header is set to application/json. It also comes with a JSON encoder, so you don't need to serialize the data before returning a response object. Take a look at a typical usage example:

from django.http import JsonResponse

def profile(request):
    json_data = {
        'name': 'Andrei',
        'location': 'Italy',
        'is_active': True,
        'age': 33
    }
    return JsonResponse(data)

Let's decompose it. The first line is the import of the JsonResponse function from the django.http library. Then, you need to define the JSON object json_data in the profile function. Finally, return this object using the JsonResponse function.

JsonResponse plays an important role in the context of the DRF, which provides useful tools for quickly creating APIs. In API development, especially using DRF, passing data in JSON format is an integral part of the customer experience. In this context, JsonResponse acts as a key component, providing a simple and efficient way to return JSON responses from API views.

DRF includes serializers that convert complex data types, such as querysets and model instances, into Python data types that can be easily converted to JSON format. JsonResponse serves as the interface between serialized data and the HTTP response, making it easy to send data in JSON format to clients consuming your API.

The importance of JsonResponse in the context of DRF is demonstrated by its ability to provide a clear mechanism for handling JSON responses and integration with many DRF functionalities. Thanks to this connection, developers can easily create modern and flexible APIs, providing clients with structured and easily digestible data in JSON format.

JsonResponse default parameters

class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)

The above line is the class signature of JsonResponse.

The first parameter, data, is a dictionary instance by default. However, if you want to pass any other JSON-serializable object as a parameter, set the safe parameter to false:

return JsonResponse(["apple", "kiwi", "banana", "lime"], safe=False)

If you pass a non-serializable object as data without setting safe to False, it will raise a TypeError.

As the official documentation points out, the JavaScript Array constructor was vulnerable before ES5. Imposters could poison it. That is why Django does not allow passing non-dictionary objects to JsonResponse objects by default. Most browsers nowadays support ES5 or newer, which removes that vulnerability. So, it is now possible to set safe=False.

The encoder parameter is the DjangoJsonEncoder from the django.core.serializers.json package. Besides primitive data types, this encoder can also handle different data types like datetime. If you use a different JSON encoder class, pass the encoder parameter to the constructor method:

response = JsonResponse(data, encoder=CustomJSONEncoder)

If you want to read more about the default encoder and many others, head to the Serializing Django objects part of the documentation.

The json_dumps_params parameter is a dictionary of keyword arguments that can be passed to the json.dumps() function. It is used to generate the response.

JsonResponse use-case example

Client-side JavaScript can be edited right in the developer tools, while code on the server isn't accessible to the client. You can end up in a situation where some people with "bad intentions" can steal your API key and use the service under your account, which may lead to data loss. To avoid this and protect the API keys, you may want to return a JSON response in Django.

To get a better idea, let's create a project "SuperHero API Search" to get the information for a specific superhero. For the sake of this exercise, you've created an account on Rapid API and subscribed to the free plan. Then you created a Django project called superheroapi. Inside this project, you have an app called call_superhero. The project diagram will look something like this:

superheroapi -> BASE_DIR
│   db.sqlite3
│   manage.py

├───call_superhero -> APP
│       admin.py
│       apps.py
│       models.py
│       tests.py
│       views.py
│       __init__.py

└───superheroapi -> CORE
        asgi.py
        settings.py
        urls.py
        wsgi.py
        __init__.py

After adding the call_superhero app to the INSTALLED_APPS list in the settings.py file, create a view function inside the views.py:

import requests
from django.http import JsonResponse


url = 'https://superhero-search.p.rapidapi.com/api/'

# In production, this should be set as an environment variable
headers = {
    'X-RapidAPI-Host': 'superhero-search.p.rapidapi.com',
    'X-RapidAPI-Key': 'your API key goes here'
}

params = {
    'hero': 'Thor'
}

def superhero_list(request):
    res = requests.get(url, headers=headers, params=params)
    return JsonResponse(res.json(), json_dumps_params={'indent': 4})

Then, add the route to the urls.py file:

from django.contrib import admin
from django.urls import path
from call_superhero.views import superhero_list

urlpatterns = [
    path('admin/', admin.site.urls),
    path('superhero/', superhero_list),
]

In the end, once you've called the python manage.py runserver command, you can go to the browser and paste the view function (for example, localhost:8000/superhero.) You'll see the response object:

{
    "id": 659,
    "name": "Thor",
    "slug": "659-thor",
    "powerstats": {
        "intelligence": 69,
        "strength": 100,
        "speed": 83,
        "durability": 100,
        "power": 100,
        "combat": 100
    },
    "appearance": {
        "gender": "Male",
        "race": "Asgardian",
        "height": [
            "6'6",
            "198 cm"
        ],
        "weight": [
            "640 lb",
            "288 kg"
        ],
        "eyeColor": "Blue",
        "hairColor": "Blond"
    },
... # other information here
}

Conclusion

This topic explored the JsonResponse class in Django and explained the importance of returning a response object as JSON.

JsonResponse and DRF work together to make it easy to create modern, easy-to-interoperate, easy-to-understand APIs where all the complexity of serializing and returning JSON data is handled by Django and DRF's built-in mechanisms.

This class accepts several parameters: encoder, safe, and json_dumps_params. All these parameters have certain default values, but they also can be changed according to what you need. In the end, we've created a project to illustrate the way you can use JsonResponse objects in Django.

"Programming is a skill best acquired by practice and example rather than from books," so go ahead and practice what you've learned!

5 learners liked this piece of theory. 1 didn't like it. What about you?
Report a typo