Handling JSON Data Serialization when Working with Django REST Framework APIs
Tags: django, restapi, python, webdev
Published: 2024-02-02 15:50:10

## Introduction

Website development, and computer programming in general, involves handling and manipulating data. Many web apps constitute database serves that hold various types of data. Client computers frequently need to retrieve or update the data, which necessitates data transmission back and forth, between the front-end and back-end.

Applications transmit data in several formats between origin and destination entities, with encoding and decoding of the data taking place at source and destination respectively. This article discusses the encoding and decoding of data in Python backend applications using JSON format, with a specific focus on Django Rest Framework APIs.

## Prerequisites
* A basic understanding of the concept of serialization
* A basic understanding of the Django REST Framework

## A Simplistic Overview

As mentioned, software systems transmit data in various formats. Common formats include **JavaScript Object Notation(JSON)**, XML, and CSV. However, web applications widely implement the JSON transmission due to JSON's compact structure and readability. Moreover, since JSON's syntax closely resembles a JavaScript's object syntax, and JavaScript is the primary language for modern web browsers, JSON enjoys robust browser and server-side support.

### Serialization
In simple terms, serialization basically means "encoding" of data. Serialization is the practice of converting a data object that constructed in one of a programming language's native data types into a format suitable for transmission, such as JSON. Python data objects, for instance, could be of any native Python data types—string, integer, list or dictionary. Serializing such an object involves converting its format from, say, a Python string to a JSON string.

### Deserialization
Deserialization could be understood as "decoding" of data at the destination. The concept is the opposite of serialization. In this case, a JSON or XML data structure is reconverted into a native type. For instance, a Python string that was processed into a JSON string at the source is reverted into a Python string. The data could then be stored in a database or used in some other Python program.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ze21agsbi7tmem5k6drc.jpg)



## Why Serialize Data?
Serialization of data intends to achieve various efficiency metrics in applications. The metrics include performance, responsiveness, speed, security etc. In the context of web applications, serializing data facilitates:
* Seamless portability of data between front-end and back-end systems written in different programming language
* Reduced network bandwidth during the transmission process since data is compacted
* Reduced network latency during transmission.
* Easy conversion of data from a complex type to a string of bytes for network transmission
* Validation and implementation of security checks for the data being transmitted

## How is Data Serialization and Deserialization achieved in Python?
Python has built-in modules that facilitate serialization and deserialization in common data formats. The most popular Python data modules include `json` and `csv`. For purposes of this article, we will not discuss working with these modules for basic implementation of serialization in Python. For more information regarding JSON and CSV formats in Python, [check out this tutorial](https://www.geeksforgeeks.org/convert-json-to-csv-in-python/).

## JSON Serialization in Django REST Framework APIs
Understanding data serialization comes in handy when working with **Application Programming Interfaces (APIs)**.  One of the primary functions of APIs is to avail data to front-end applications. When building APIs that deliver data to the front-end, backend engineers define data serialization mechanisms in the backend logic.
 
In **Django REST Framework (DRF)**, it is common practice for backend engineers to create a **serializers.py** file that defines an application's data serialization logic. The serialization logic, in this case, constitutes one or several Python class objects. The class objects are defined therein, imported into **views.py** file and applied to API view classes or functions.

To recap a typical Django web application file structure, assume you are designing APIs of a restaurant web app. Your app’s file structure, including the serializers.py, might look something like this:
```
  ->Project’s root directory
    ->manage.py
    ->restaurant_app directory
	  -> urls.py
	  -> views.py
	  -> models.py
	  -> serializers.py
```
Your project’s root directory might host several applications with different APIs defined. Each application should have its serializers.py file.

### A Typical Serializer Class
To define a typical serializer Python class object for your API, you need to provide the following inside your serializer class definition:
* A nested Meta class
* Your model
* The model fields to be serialized

Assume in your restaurant’s model.py file you have defined the following fields:
```python
from Django.db import models

# Create your models here
class Available_Foods(models.Model):
    """Food types in my restaurant"""
	id = models.IntegerField(primary_key=True)
	food_name = models.CharField(max_length=255, null=True)
```
The model above has two fields that need to be serialized: id and food_name. Your serializer.py might look something like this:
```python
# serializer.py
from rest_framework import serializers
from .models import Available_Foods

class Available_Foods_Serializer(serializers.ModelSerializer):
	"""Serializes my model fields"""
	class Meta:
		model = Available_Foods
		fields = ['id', 'name']
```
In this typical serializer class, you need to import the **serializers** module, which DRF provides. The module contains a Python class object known as **ModelSerializer** which will act as a super class to all the classes you define in the serializers.py file.

Inside your custom serializer class, you need to provide a nested class, Meta, that specifies the model whose fields need to be serialized. Additionally, you need explicitly state the model fields to include in the serialization. In some cases you may not need to serialize all fields, and hence, DRF serialization offers this flexibility. If you need to serialize all fields without explicitly stating them in the **fields** variable array, you can replace the fields array value with this Python magic method:

```python
fields  =  __all__
```

After you have defined your serializer class and the fields you need serialized, you can go ahead and apply the serializer class(es) to your API views like this:
1.Import your custom serializer class(es) into your views.py file

```python
from .serializers import Available_Foods_Serializer
```
2.Define your view class(es), if not already defined. 
3.Enter your serializer class at the beginning of your API definition, after the line that defines the queryset which the API will act upon.
```python
class ListFoods(generics.ListAPIView):
    """Lists all available food items"""
    queryset = Available_Foods.objects.all()
    serializer_class = Available_Foods_Serializer
```

### Sending Serialized Data to a DRF API Endpoint
Using our restaurant project, assume you want to create a food item that your restaurant offers, identified by ID and name, and store it in the database. In a development environment, you will need to enter the API endpoint, which should already be defined in your application's **urls.py** file, in a browser, with some JSON formatted data. Look at the example below:

Assume you have this endpoint for populating your database with available foods:

**/root_url/restaurant_app/create-food-item/**

DRF’s browsable API provides an effective platform for working with DRF APIs in your browser. Your **POST request** data to the above endpoint might look something like this:
```json
{
	"id": 1,
	"food_name": "pizza"
}
```
Note the format of the request data. The format is JSON—key-value pairs with all strings in double quotations. The data is said to be JSON serialized, ready for transmission. If you send a POST request with this data to the above endpoint, the data will be deserialized into a Python object and stored in the database.

The server may send a similar response as below if your create operation was a success. Note that the response contains the object you just created in JSON format.
```
POST /restaurant_app/create-food-item/
HTTP 201 CREATED OK
Allow: POST
Content-Type: application/json

{
	"id": 1,
	"food_name": "pizza"
}
```

If you inspect the server's response header’s **Content-Type** field value,  it displays **application/json**. The Content-Type field returns the data format of the response body, which, in this case, is JSON.

## Conclusion
Working with the JSON data format when DRF APIs could be challenging for first timers. While this article provides useful information for those getting started with data serialization in DRF APIs, it is certainly not exhaustive.

This article fails to mention the mistakes that developers can commit while defining models and serialization classes in Django. The mistakes mess up serialized outputs and throw errors when sending requests to endpoints. Additionally, a backend engineer may need to develop more complex serialization class objects, not captured in this article, based on the front-end consumer application’s needs.

Nevertheless, this article offers a decent entry point to those who are getting started with API serialization in Django. Happy coding!