[DRF] Serialization / Deserialization 동작 변경 - to_internal_value와 to_representation
Serialization과 Deserialization
Serialization과 Deserialization은 사용자와 클라이언트가 API에서 데이터를 읽고 쓸 수 있도록 API에서 데이터를 표현하고 전송하는 데 사용되는 기능이다.
Serialization 직렬화
Serialization은 데이터 객체를 JSON 또는 XML 등의 포맷으로 변환하는 과정으로 DRF에서는 Serializer 클래스를 사용하여 객체를 직렬화할 수 있다. Serializer는 ModelSerializer, Serializer 및 다른 유형의 Serializer 클래스를 포함하는 다양한 유형이 있고 Serializer를 사용하면 모델 인스턴스를 쉽게 JSON, XML 또는 다른 포맷으로 변환할 수 있다.
Deserialization 역직렬화
Deserialization은 이름에서 볼 수 있듯이 직렬화의 반대 과정, 즉 JSON 또는 XML 등의 포맷의 데이터를 Python 객체로 변환하는 과정이다. DRF에서는 JSONParser, XMLParser 및 다른 Parser class를 사용하여 데이터를 파싱한다. Serializer에서 데이터를 받아들이는 경우 DRF는 데이터를 파싱하고 Serializer를 사용해서 Python 객체로 변환한다.
to_representation()와 to_internal_value()
이 두가지 메서드는 Django REST framework (DRF)의 Serializer 클래스의 고급 기능 중 일부이다. DRF에서 복잡한 데이터 시리얼화 및 데이터 유효성 검사 로직을 작성할 때 이러한 메서드를 사용해 커스터마이징 할 수 있다.
to_representation()
to_representation()는 serializer가 Python 객체를 JSON으로 직렬화 할 때 호출되는 메서드이다. 이 메서드를 오버라이드하면 직렬화 할 데이터가 JSON으로 변환되기 전 해당 데이터를 처리하거나 수정이 가능하다.
class ExampleSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
context = serializers.CharField(max_length=100)
def to_representation(self, instance):
representation = super().to_representation(instance)
representation['context'] = representation['context'].upper()
return representation
👉🏻 serializer가 생성한 데이터의 context의 필드 값을 대문자로 변환해 반환한다.
👉🏻 super()를 사용해 상위 Serializer 클래스의 기본 동작을 유지하면서, 일부 동작을 추가하거나 수정할 수 있다.
to_internal_value()
to_internal_value 메서드는 request data에서 파싱된 값을 사용하기 적합한 Python 데이터 타입으로 변환하는 역할을 한다. 예를 들어 JSON 형태의 request data를 파싱해서 필요한 필드 값들을 추출해야 할 때 사용할 수 있다.
from rest_framework import serializers
class ExampleSerializer(serializers.Serializer):
first_field = serializers.IntegerField()
def to_internal_value(self, data):
fisrt_field = int(data.get('first_field'))
return {'first_field': first_field}
👉🏻 request data에서 first_field 필드의 값을 추출하여 정수형으로 변환한 후, first_field 필드를 가진 딕셔너리 형태의 결과값을 반환하는 예시코드 이다. to_internal_value 메서드를 구현하면 DRF가 파싱한 request data를 적합한 Python 객체로 변환할 수 있다.
def to_internal_value(self, data):
data['fisrt_field'] = int(data.get('first_field'))
return super(ExampleSerializer).to_internal_value(data)
또한 위와같이 리턴하게 되면 부모 클래스인 serializers.Serializer의 to_internal_value() 메서드를 호출하여 해당 데이터를 시리얼라이저가 표현하는 데이터로 변환한다. 부모 클래스의 검증 절차를 그대로 따르면서 자식 클래스에서 추가적인 검증 로직 구현이 가능하기 때문에 시리얼라이저에서 사용자 정의 시리얼라이저 메소드를 정의할 때 주로 사용한다.