The Boxer
pydantic 모델 파싱시 비어있는 필드에 대해 본문
728x90
반응형
pydantic 모델 파싱시 주의 사항
- request나 response로 넘어온 body data를 pydantic이 model로 파싱하는 과정에서 정의된 필드가 비어있는 경우 에러를 던진다.
에러가 발생하는 예시
from pydantic import BaseModel
class Foo(BaseModel):
id: int
name: str
def service_method() -> dict:
return { "name": "testing" }
def controller_method() -> Foo:
result = service_method()
return Foo(**result)
controller_method()
- pydantic은 모델로 데이터를 파싱하는 과정에서 파싱이 불가능한 값이 들어온 경우 에러를 던진다.
- 위 경우에서 Foo 모델은 반드시 int형의 id와 string형의 name 필드가 존재해야 하며, 이를 만족하지 못하는 경우 에러를 던진다.
None에 대해 간과한 점
- python에서 None은 값일 뿐 아니라 독립적인 type으로도 구분이 된다.
- dictionary에서 빈값은 None type으로 처리된다. 즉, 위 경우에서 id 필드가 포함되지 않은 값은 pydantic이 파싱하는 과정에서 None 타입으로 인식하고 int 형이 아니기 때문에 에러를 던졌다고 이해할 수 있다.
- 결국 위에서 정의한 모델은 Optional 조건을 추가하거나 None 타입을 허용하게 하여 다음과 같이 수정해야 한다.
class Foo(BaseModel):
# Optional 사용
id: Optional[int]
# Union으로 타입 지정
id: Union[int, None]
name: str
- 이렇게 하면 id 필드가 포함되지 않는 경우에도 에러를 던지지 않고 파싱이 가능해진다.
모델에 대한 정확한 정의
- pydantic이 지정한 타입을 보장해 주는 역할을 한다고 했는데, 위 상황에서 pydantic이 에러를 던지지 않고 필드를 빈값으로 처리해 진행한다면 오히려 정확한 기능을 제공하지 않는 것으로 볼 수 있다.
- id가 int형이 아닌 None 타입이 되므로
- id
- 결국 위와 같은 문제를 겪지 않으려면 통신 과정에서 정확한 모델에 대한 정의가 필요하고, 이를 강제로 지킬 수 있도록 하는게 중요할 것 같다.
Response 처리
- response를 처리하는 과정에서 None 값을 가진 필드를 제외하고 반환하고자 하는 경우 다음과 같이 처리할 수 있다.
인스턴스를 json으로 변환하는 과정에서 제외
def controller_method() -> Foo:
result = service_method()
return Foo(**result).json(exclude_none=True)
print(controller_method())
> {'name': 'testing'}
- fastapi의 controller단에서 response_model 로 설정한 경우 response_model_exclude_none 옵션을 통해 None 값을 제외시킬 수 있다.
response_model_exclude_none 옵션 설정
@app.get("/foo", response_model=Foo, response_model_exclude_none=True)
def controller_method() -> Foo:
result = service_method()
return Foo(**result).json(exclude_none=True)
728x90
반응형
'Python' 카테고리의 다른 글
python metaclass (0) | 2022.08.06 |
---|---|
python decorator (0) | 2022.08.03 |
python mutable, immutable (0) | 2022.07.23 |
python object interning (0) | 2022.07.22 |
python dataclass (0) | 2022.07.21 |
Comments