Pydantic을 사용한 직렬화와 역직렬화
직렬화는 객체 데이터를 통신하기 쉬운 포맷(Byte, CSV, JSON 등) 형태로 만들어주는 작업을 말하며, 역직렬화는 반대로 포맷(Byte, CSV, JSON 등)형태에서 객체로 변환하는 과정을 말한다.
- 직렬화: 객체들의 데이터를 전송할 수 있도록 특정 포맷 상태로 변환하는 것
- 역직렬화: 직렬화된 데이터를 다시 객체 형태로 만드는 것
위키백과에서 말하는 직렬화
직렬화(直列化) 또는 시리얼라이제이션(serialization)은 컴퓨터 과학의 데이터 스토리지 문맥에서 데이터 구조나 오브젝트 상태를 동일하거나 다른 컴퓨터 환경에 저장(이를테면 파일이나 메모리 버퍼에서, 또는 네트워크 연결 링크 간 전송)하고 나중에 재구성할 수 있는 포맷으로 변환하는 과정이다.[1] 오브젝트를 직렬화하는 과정은 오브젝트를 마샬링한다고도 한다.[2] 반대로, 일련의 바이트로부터 데이터 구조를 추출하는 일은 역직렬화 또는 디시리얼라이제이션(deserialization)이라고 한다.
이러한 직렬화와 역직렬화에 대하여 깊게 공부하는 포스팅은 아니므로, 여기까지만 간단하게 직렬화와 역직렬화에 대하여 정리하고, Pydantic에서 직렬화 그리고 역직렬화에 대해서 알아보도록한다.
환경 설정
- python: 3.11.3
- pyadantic: 2.7.1
- pydantic_core: 2.18.2
역직렬화
Pydantic의 BaseModel을 사용하여 객체를 만들경우, 역직렬화라고 이야기 할 수 있다. 즉, 이전 포스팅에서 정리한 dict와 JSON 문자열을 사용하여 Pydantic 모델을 생성한 방법이 Pydantic을 사용한 역직렬화으로 볼 수 있다.
from pydantic import BaseModel
class Person(BaseModel):
first_name: str
last_name: str
age: int
data = {'first_name': 'Seongyeon', 'last_name': 'Kim', 'age': 29}
json_data = '{"first_name": "Seongyeon", "last_name": "Kim", "age": 29}'
# deserialize 방법 1
p1 = Person(first_name='Seongyeon', last_name='Kim', age=29)
# deserialize 방법 2
p2 = Person(**data)
# deserialize 방법 3
p3 = Person.model_validate(data)
# deserialize 방법 4
p4 = Person.model_validate_json(json_data)
직렬화
Pydantic을 사용한 직렬화 방법은 역직렬화의 정의(직렬화된 데이터를 다시 객체 형태로 만드는 것)을 그대로 준수한다. 즉 dict 로 만들거나, JSON 문자열로 반환할 수 있다.
- dict로 변환: model_dump()
- JSON문자열로 변환: model_dump_json()
# serialize 방법 1
print(p1.__dict__) # 출력: {'first_name': 'Seongyeon', 'last_name': 'Kim', 'age': 29}
# serialize 방법 2
print(p1.model_dump()) # 출력: {'first_name': 'Seongyeon', 'last_name': 'Kim', 'age': 29}
print(type(p1.model_dump())) # 출력: <class 'dict'>
# serialize 방법 3
print(p1.model_dump_json()) # 출력: {"first_name": "Seongyeon", "last_name": "Kim", "age": 29}
print(p1.model_dump_json()) # 출력: <class 'str'>
model_dump_json()의 경우 다양한 설정 값이 존재하여, 유용하게 사용할 수 있다.
- indent: JSON 출력의 들여스기 수준을 지정한다. None(값을 설정하지 않음) 경우, 출력은 축약형(압축된 형태)으로 생성된다.
- exclude: JOSN 출력에서 제외할 필드를 지정한다. 리스트 혹은 딕셔너리 형태로 지정할 수 있다.
- context: 시리얼라이저로 전달할 추가 컨텍스트를 지정한다. 사용자 정의 직렬화 로직에 사용하면 유용하다.
- by_alias: True로 설정 시, 필드 이름 대신 별칭(alias)을 사용하여 JSON을 직렬화 한다.
- exclude_unset: True로 설정 시, 명시적으로 설정되지 않은 필드를 JSON 출력에서 제외한다.
- exclude_default: True로 설정 시, 기본값으로 설정된 필드를 JSON 출력에서 제외한다.
- exclude_none: True로 설정 시, 값이 None인 필드를 JSON 출력에서 제외한다.
- round_trip: True로 설정 시, 덤프된 값이 Json[T]와 같은 비멱등(non-indempotent) 타입의 입력으로 보장한다.
- warnigs: 직렬화 오류를 처리하는 방식을 지정한다.
- False, none: 오류를 무시한다.
- True, warn: 오류를 로그로 기록한다.
- error: PaydanticSerializationError를 발생시킨다.
- serialize_as_any: True 설정 시, 필드의 덕 타이핑 직렬화 동작을 활성화 한다.
from pydantic import BaseModel
class Person(BaseModel):
first_name: str
last_name: str
age: int
# Person 인스턴스 생성
person = Person(first_name='Seongyeon', last_name='Kim', age=29)
# 기본 설정으로 직렬화
json_output = person.model_dump_json()
print(json_output) # 출력: {"first_name": "Seongyeon", "last_name": "Kim", "age": 29}
# 들여쓰기를 사용하여 직렬화
json_output_pretty = person.model_dump_json(indent=2)
print(json_output_pretty)
# age 필드를 제외하고 직렬화
json_output_exclude_age = person.model_dump_json(exclude={'age'})
print(json_output_exclude_age)
관련 공식 문서
Serialization - Pydantic
Serialization Beyond accessing model attributes directly via their field names (e.g. model.foobar), models can be converted, dumped, serialized, and exported in a number of ways. Serialize versus dump Pydantic uses the terms "serialize" and "dump" intercha
docs.pydantic.dev
요약
from pydantic import BaseModel
class Person(BaseModel):
first_name: str
last_name: str
age: int
data = {'first_name': 'Seongyeon', 'last_name': 'Kim', 'age': 29}
json_data = '{"first_name": "Seongyeon", "last_name": "Kim", "age": 29}'
# deserialize 방법 1
p1 = Person(first_name='Seongyeon', last_name='Kim', age=29)
# deserialize 방법 2
p2 = Person(**data)
# deserialize 방법 3
p3 = Person.model_validate(data)
# deserialize 방법 4
p4 = Person.model_validate_json(json_data)
# serialize 방법 1
print(p1.__dict__) # 출력: {'first_name': 'Seongyeon', 'last_name': 'Kim', 'age': 29}
# serialize 방법 2
print(p1.model_dump()) # 출력: {'first_name': 'Seongyeon', 'last_name': 'Kim', 'age': 29}
print(type(p1.model_dump())) # 출력: <class 'dict'>
# serialize 방법 3
print(p1.model_dump_json()) # 출력: {"first_name": "Seongyeon", "last_name": "Kim", "age": 29}
print(p1.model_dump_json()) # 출력: <class 'str'>
print(p1.model_dump_json(indent=2)) # escape characters 를 보기좋게 사용할 수 있다.
print(p1.model_dump_json(exclude={'age'})) # 출력: {"first_name": "Seongyeon", "last_name": "Kim"} exclude 옵션을 사용하여 특정 필드를 제외할 수 있다.
'개인공부' 카테고리의 다른 글
[ SQLAlchemy ] selecteload 와 joinload의 차이는 무엇일까? (1) | 2024.11.12 |
---|---|
[ Django ] 유저 모델을 설계할 때, User, AbstractBaseUser, AbstractUser 중 어떤 클래스를 사용해야 할까? (0) | 2024.11.10 |
[ Pydantic ] Pydantic의 BaseModel 사용하기 (0) | 2024.05.28 |
[ JPA ] 다양한 어노테이션을 사용한 효과적인 엔터티 매핑_2.연관관계 매핑 (0) | 2024.02.12 |
[ JPA ] 다양한 어노테이션을 사용한 효과적인 엔터티 매핑_1.객체와 테이블 매핑 (0) | 2024.02.12 |