Serializer: o que é e como funciona no Django Rest Framework

Serializer: o que é e como funciona no Django Rest Framework
Laís Urano
Laís Urano

Compartilhe

Introdução

O desenvolvimento de APIs é uma parte fundamental na construção de sistemas modernos, pois ela permite a comunicação eficiente e flexível entre diferentes partes de uma aplicação ou sistemas distintos. E, no contexto do desenvolvimento em Django, o Django Rest Framework (DRF) apresenta ferramentas para a criação de APIs robustas.

Entretanto, nesse processo, precisamos destacar um componente essencial: os serializers do DRF, que atuam na manipulação e transmissão de dados. Mas afinal, o que é um serializer e como ele funciona no desenvolvimento de APIs utilizando o Django Rest Framework?

Vamos descobrir tudo isso ao longo desta leitura!

Banner promocional da Alura, com um design futurista em tons de azul, apresentando dois blocos de texto, no qual o bloco esquerdo tem os dizeres:

O que é um serializer?

Um serializer (em português, serializador) é um componente de software que converte dados complexos, como objetos ou estruturas de dados, em algum formato que pode ser facilmente transmitido ou armazenado e, posteriormente, reconstruído. Esse processo de conversão é conhecido como serialização.

Ao realizar a conversão de um objeto ou conjunto de dados, você o transforma em uma representação linear ou em um formato específico, como JSON, XML, YAML ou outros formatos binários. Essa representação serializada pode ser transmitida pela rede, gravada em um arquivo ou armazenada em um banco de dados.

Serializadores também fazem o processo oposto, chamado de desserialização, que reconstrói a estrutura original dos dados a partir da representação serializada. Isso permite que os dados sejam transmitidos, armazenados ou compartilhados entre diferentes sistemas de maneira eficiente.

Como funciona o serializer no DRF?

Assim como o Django utiliza o ORM (Object-Relational Mapping) para simplificar a interação com classes de modelos e facilitar a comunicação eficiente com o banco de dados, o Django REST Framework emprega uma abordagem semelhante ao criar serializers com classes em Python otimizando a manipulação de dados em APIs.

Podemos conferir um esquema de como acontece esse processo:

A imagem apresenta um fundo verde-escuro e uma iluminação verde-claro no canto superior esquerdo. O diagrama mostra 3 blocos, sendo o primeiro um azul escuro escrito “DATABASE” com letras brancas e duas setas brancas mostram a conexão de ida e volta com o bloco de “MODELS” em azul claro com letras pretas. O bloco de “MODELS” faz a conexão das duas setas de ida e volta com o bloco verde claro escrito “SERIALIZER” com letras pretas. E por fim, o bloco “SERIALIZER” apresenta duas setas de ida e volta com o texto “JSON, XML ou outros tipos de dados”. No canto inferior esquerdo apresenta várias barras na diagonal na cor verde e no canto inferior direito temos a logo da Alura.

Como podemos notar, a interação dos tipos de dados se dá com o model interagindo com o banco de dados por meio do ORM, na qual executa as operações de consulta, atualização, criação ou exclusão de dados no banco de dados.

Os dados retornados do banco, nesse processo, são querysets ou instâncias da classe criada no Model, que podemos definir como uma representação da consulta ao banco de dados no Django em formato de objetos complexos.

Esses dados são enviados para os serializadores, que são classes que especificam como converter objetos complexos, em formatos de dados típicos do python, como dicionários que podem ser facilmente renderizados em JSON, XML, entre outros.

Para compreender melhor, vamos analisar o funcionamento dessa conversão no projeto de uma escola que utiliza um modelo de cadastro de alunos, no código a seguir:

# app ‘escola’ no arquivo ‘models.py’

from django.db import models

class Aluno(models.Model):
    nome = models.CharField(max_length = 30)
    rg = models.CharField(max_length=9)
    cpf = models.CharField(max_length=11)
    data_nascimento = models.DateField()

    def __str__(self):
        return self.nome

Se realizarmos uma consulta ao banco de dados para recuperar todos os registros presentes na tabela correspondente a esse modelo de classe, temos a seguinte resposta:

A imagem apresenta um fundo verde-escuro e uma iluminação verde-claro no canto superior esquerdo. O foco é o terminal interativo do python com duas linhas de comando. A primeira diz “dados_dos_alunos = Aluno.objects.all()” e a segunda tem “dados_dos_alunos”. A próxima linha mostra a resposta “<QuerySet [<Aluno: Lais>, <Aluno: Gui>, <Aluno: Ana>]>”. No canto inferior esquerdo apresenta várias barras na diagonal na cor verde e no canto inferior direito temos a logo da Alura.

Essa informação de <QuerySet [<Aluno: Lais>, <Aluno: Gui>, <Aluno: Ana>]> nada mais é que a representação complexa de todos os objetos que foram guardados no banco de dados, retornados do modo que definimos no método __str__ do modelo.

Contudo, para tornar esses dados mais acessíveis e intercambiáveis, precisamos transformar esse objeto complexo em um tipo de dado do Python que seja facilmente serializado, especialmente quando lidamos com a transmissão de dados por meio de APIs ou a representação em formato JSON.

Para isso, criamos um serializer para esse modelo, estruturando o seguinte:

# app ‘escola’ no arquivo ‘serializers.py’

from rest_framework import serializers
from escola.models import Aluno

class AlunoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Aluno
        fields = ['id','nome','rg','cpf','data_nascimento']

Nesse caso, transformar o QuerySet em um tipo de dado Python significa que queremos uma representação mais simples dos dados, como em uma lista de dicionários ou uma lista de strings. Fazendo essa conversão no terminal, obtemos a seguinte resposta:

A imagem apresenta um fundo verde-escuro e uma iluminação verde-claro no canto superior esquerdo. O foco é o terminal interativo do python com duas linhas de comando. A primeira diz “dados_serializados = AlunoSerializer(dados_dos_alunos,many=True)” e a segunda tem “dados_serializados.data”. A próxima linha mostra a resposta “[OrderedDict({'id': 1, 'nome': 'Lais', 'cpf': '00000000000', 'rg': '000000000', 'data_nascimento': '2024-01-04'}), OrderedDict({'id': 2, 'nome': 'Gui', 'cpf': '01234567890', 'rg': '012345678', 'data_nascimento': '2024-01-04'}), OrderedDict({'id': 3, 'nome': 'Ana', 'cpf': '12345678900', 'rg': '123456789', 'data_nascimento': '2024-01-04'})]”. No canto inferior esquerdo apresenta várias barras na diagonal na cor verde e no canto inferior direito temos a logo da Alura.

Agora, dados_serializados é uma lista de dicionários que pode ser facilmente convertida em JSON para ser utilizada em APIs ou em outros contextos que exigem uma representação mais simples e universal dos dados.

Além disso, podemos utilizar o serializer para filtrar os dados que são importantes para serem adicionados na nossa API. No exemplo a seguir, alteramos a classe do serializer para receber todos os campos, com exceção do data_nascimento e transformamos esses dados em um JSON:

A imagem apresenta um fundo verde-escuro e uma iluminação verde-claro no canto superior esquerdo. O foco é o terminal interativo do python com cinco linhas de comando. A primeira faz uma alteração na classe AlunoSerializer e tira o campo ‘data_nascimento’ do parâmetro fields, a segunda tem “dados_serializados = AlunoSerializer(dados_dos_alunos,many=True)” novamente e a terceira faz o import através do “from rest_framework.renderers import JSONRenderer”. A próxima linha mostra faz a conversão ”dados_json = JSONRenderer().render(dados_serializados.data)” e em seguida a outra linha pede os resultados através de “dados_json”. A ultima linha mostra o resultado da conversão “b'[{"id":1,"nome":"Lais","cpf":"00000000000","rg":"000000000"},{"id":2,"nome":"Gui","cpf":"01234567890","rg":"012345678"},{"id":3,"nome":"Ana","cpf":"12345678900","rg":"123456789"}]'”. No canto inferior esquerdo apresenta várias barras na diagonal na cor verde e no canto inferior direito temos a logo da Alura.

Este processo de transformação é essencial para facilitar a comunicação entre sistemas heterogêneos e garantir a interoperabilidade dos dados. Mas além disso, o que faz o serializer ser tão essencial na criação de APIs com o Django Rest Framework?

A importância de serializer no DRF

Como vimos, os serializers permitem a transformação eficiente de objetos complexos, como modelos de banco de dados Django, em formatos facilmente transmitidos pela web, como JSON. Eles desempenham um papel crucial na representação dos dados e na comunicação entre o backend e o frontend.

Algumas características que tornam o serializer tão importante são:

Validação de dados

Ao receber dados por meio de solicitações, os serializers fornecem uma camada de validação. A validação inclui a verificação de tipos de dados, restrições de comprimento, integridade e qualquer lógica de validação personalizada definida por quem está desenvolvendo. Isso é vital para garantir a integridade dos dados e prevenir inconsistências no backend.

Facilidade de desserialização

Os serializers do DRF simplificam a desserialização de dados recebidos em objetos utilizáveis no backend, através da conversão de dados formatados (por exemplo, JSON) em objetos Python utilizáveis no backend. Isso é crucial para traduzir os dados recebidos em um formato manipulável no sistema.

Tratamento de relacionamentos e dados aninhados

Em casos de relacionamentos complexos ou dados aninhados, os serializers do DRF oferecem maneiras eficazes de lidar com essas estruturas de forma organizada. Isso é muito útil em situações em que os modelos têm associações complexas ou quando há necessidade de representar dados hierárquicos.

Flexibilidade e customização

Os Serializers do DRF oferecem um alto nível de flexibilidade, permitindo personalizar a serialização e desserialização conforme necessário. Isso inclui a capacidade de criar campos personalizados, validar dados com lógica específica do aplicativo e adaptar a representação dos dados para atender aos requisitos específicos da aplicação.

Representação padronizada

Os serializers do DRF permitem definir como os dados devem ser representados na saída da API. Isso garante uma consistência na estrutura da resposta, facilitando a compreensão e o consumo dos dados por parte dos clientes da API.

A capacidade dos serializers de transformar dados complexos em formatos interoperáveis não apenas facilita a representação padronizada e a validação eficaz, mas também desempenha um papel crucial na escolha entre os tipos de serializers a serem utilizados no projeto.

Tipos de serializer no DRF

No DRF há diversos tipos de serializers, sendo os dois principais: ModelSerializer e Serializer. Ambos são usados para definir como os dados são serializados e desserializados, mas têm propósitos ligeiramente diferentes.

ModelSerializer

O ModelSerializer é um tipo de serializer especializado para interagir com modelos do Django. Ele simplifica muito o processo de criação de serializers para modelos, pois ele automaticamente infere muitos detalhes com base nos modelos.

No exemplo anterior, utilizamos o serializer do tipo Model, como podemos ver a seguir e podemos definir o atributo fields com um valor especial 'all' para indicar que todos os campos do modelo devem ser usados:

from rest_framework import serializers
from escola.models import Aluno

class AlunoModelSerializer(serializers.ModelSerializer):
       class Meta:
           model = Aluno
           fields = '__all__'

O ModelSerializer automaticamente cria campos com base nos campos do modelo, trata relacionamentos automaticamente e fornece métodos padrão para criação e atualização .create() e .update().

Serializer

Ao contrário do ModelSerializer, que é otimizado para interagir diretamente com modelos do Django, o Serializer é um tipo mais genérico que oferece maior controle manual sobre como os dados são serializados e desserializados. É útil para definir campos manualmente, lidar com lógica personalizada de validação ou quando está trabalhando com dados que não estão diretamente associados a modelos do Django.

Adaptando o exemplo anterior para utilizarmos esse novo tipo, fizemos o seguinte código:

   from rest_framework import serializers

   class AlunoSerializer(serializers.Serializer):
       id = serializers.IntegerField(read_only=True)
       nome = serializers.CharField(max_length=30)
       cpf = serializers.CharField(max_length=11)
       rg = serializers.CharField(max_length=9)
       data_nascimento = serializers.DateField()

Perceba que o Serializer oferece maior flexibilidade, mas requer definição manual de todos os campos e lógica associada.

Além disso, é necessário fornecer implementações personalizadas para os métodos create e update. Esses métodos definem como os dados são tratados ao criar ou atualizar objetos no banco de dados, como complementado a seguir:

    def create(self, validated_data):
        return Aluno.objects.create(**validated_data)

    def update(self, instance, validated_data):
       instance.nome = validated_data.get('nome', instance.nome)
       instance.cpf = validated_data.get('cpf', instance.cpf)
       instance.rg = validated_data.get('rg', instance.rg)
instance.data_nascimento = validated_data.get('data_nascimento', instance.data_nascimento) 
instance.save()
        return instance

Ambos os tipos de serializers fornecem funcionalidades para validar e processar dados recebidos, bem como transformá-los em formatos como JSON para serem enviados pela web. A escolha entre ModelSerializer e Serializer depende da complexidade do seu modelo e dos requisitos específicos de seu aplicativo. O ModelSerializer é mais conveniente quando você está trabalhando com modelos do Django, enquanto o Serializer oferece mais controle em situações mais personalizadas.

Você pode ler a documentação do serializer para escolher qual tipo se adequa mais ao projeto que você está desenvolvendo.

Conclusão

Ao combinar as possibilidades do Django Rest Framework com a flexibilidade e eficiência dos serializers, as pessoas desenvolvedoras podem criar APIs robustas que atendem aos mais altos padrões de qualidade e desempenho.

Afinal, os serializers no DRF possuem a capacidade de simplificar e aprimorar esse processo de desenvolvimento de APIs. Eles são componentes essenciais que facilitam a manipulação eficiente de dados, garantindo a consistência na representação, validação e transmissão de informações entre sistemas diversos.

Com os serializers do DRF, devs podem criar APIs poderosas e escaláveis, promovendo uma comunicação eficiente e coesa entre o backend e o frontend de suas aplicações.

Que tal dar um mergulho ainda mais profundo? Deixamos aqui algumas referências para te ajudar nos seus estudos de Django Rest Framework:

Laís Urano
Laís Urano

Laís é monitora da Escola de Programação e Graduanda em Engenharia Elétrica na UFPI. Ama aprender mais sobre tecnologias e atua no fórum na categoria de Python.

Veja outros artigos sobre Programação