Jost Do It.

그냥 IT해.

서버 및 환경/Utils

[FastAPI] 딕셔너리 내 null 값을 return 하는 법

그냥하Jo. 2024. 5. 17. 09:46
반응형

상황

사내 API에서는 요청 쿼리의 결과 값에 wrapper를 씌워서 아래와 같이 내부 정의 응답코드, 요청 url 쿼리, data 등을 출력한다.

 

정상 응답 결과

 

즉, 실제 결과는 data 파라미터에 딕셔너리 형태로 출력되는데, 여기서 data에 null 출력을 위해 nan, None 값이 포함되면 다음 에러가 발생한다.

Traceback (most recent call last):
  File "/home/mining/projects/finance_advisor/some_money/somemoney_api_server/somemoney_api_server/sub_noAuth.py", line 215, in api_middleware
    response = await call_next(request)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/middleware/base.py", line 46, in call_next
    raise app_exc
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/middleware/base.py", line 36, in coro
    await self.app(scope, request.receive, send_stream.send)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/exceptions.py", line 93, in __call__
    raise exc
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
    await self.app(scope, receive, sender)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
    raise e
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/routing.py", line 670, in __call__
    await route.handle(scope, receive, send)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/routing.py", line 266, in handle
    await self.app(scope, receive, send)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/routing.py", line 65, in app
    response = await func(request)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/fastapi/routing.py", line 227, in app
    raw_response = await run_endpoint_function(
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/fastapi/routing.py", line 160, in run_endpoint_function
    return await dependant.call(**values)
  File "/home/mining/projects/finance_advisor/some_money/somemoney_api_server/somemoney_api_server/api/api_v3/endpoints/etc.py", line 261, in dartgpt_summary
    return JSONResponse(response_wrapper(request, results))
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/responses.py", line 187, in __init__
    super().__init__(content, status_code, headers, media_type, background)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/responses.py", line 49, in __init__
    self.body = self.render(content)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/site-packages/starlette/responses.py", line 190, in render
    return json.dumps(
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/home/mining/.conda/envs/some_money_api/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
ValueError: Out of range float values are not JSON compliant

 

 

사내에서는 다음 에러로 null 값을 string으로 감싸 "null" 등으로 출력하고 있었는데, null 값 출력 자체가 필요한 상황이라 이번 기회에 변경하게 됐다.

 

 

해결 방법

API 의 디폴트 출력 클래스를 변경해주면 된다.

우선 orjson 라이브러리를 설치하자.

orjson은 json파일을 읽고 쓰는데 사용되는 라이브러리 중 하나이다.

 

pip install orjson

 

 

다음으로 API의 출력 형식을 다음과 같이 설정해주면 된다.

from fastapi import FastAPI
from fastapi.responses import ORJSONResponse

router = FastAPI(default_response_class=ORJSONResponse)
[...]

 

 

일부 라우터에서 출력 형식을 다음과 같이 변경하는 것도 가능하다.

from fastapi import APIRouter
from fastapi.responses import ORJSONResponse

router = APIRouter(default_response_class=ORJSONResponse)
[...]

 

 

수정하고 값에 None을 넣어 출력하면 다음과 같이 null로 나오는걸 확인할 수 있다.

{
  "api_name": "/no_auth/api/v3/dartgpt_summary.json",
  "data": [
    {
      "time": null,
      "code": "A413640",
      "dart_report_date": null,
      "dart_report_type": null,
      "data": null
    }
  ],
  "error_msg": "",
  "request": "{query_params:[[stocks,A413640]],path_params:[]}",
  "return_code": "00"
}

 

 

Reference

반응형