question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot control json serialization with custom response_class

See original GitHub issue
class CustomJSONResponse(JSONResponse):
    media_type = "application/json"

    def render(self, content: typing.Any) -> bytes:
        return dumps(content)

With dumps being a custom function, managing datetime values specifically.

@router.post("/requests")
async def insert_user_request(request: Request):
   return CustomJSONResponse(content={"timestamp": datetime.now()}, status_code=HTTP_201_CREATED)

Will work as expected but

@router.post("/requests", response_class=CustomJSONResponse, status_code=HTTP_201_CREATED)
async def insert_user_request(request: Request):
    return {"timestamp": datetime.now()}

Will fail to use the custom dump function.

The cause is in https://github.com/tiangolo/fastapi/blob/master/fastapi/routing.py#L190 : serialize_response (which calls jsonable_encoder) is called before the response_class instantiation (https://github.com/tiangolo/fastapi/blob/master/fastapi/routing.py#L201) so datetime values are converted to str prematurely.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:6
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

6reactions
nguyentcommented, Jan 7, 2022

Looks like on the pydantic side there is also no real easy way to use our own JSON serializer - which would be very useful since people may want to do serialization differently (for instance when returning nan from pandas / numpy).

+1

I’m currently using FastAPI for an API migration and want to use a custom json encoder for parity reasons. I discovered this after diffing responses from both APIs.

A small example of what I’m seeing (this timestamp is from a pandas dataframe):

legacy timestamp: "2022-01-06 00:00:00+00:00"
fastapi timestamp: "2022-01-06T00:00:00+00:00"

Current FastAPI code

(shortened version of the current code in get_request_handler)

raw_response = await run_endpoint_function(...)
response_data = await serialize_response(response_content=raw_response, ...)
response = actual_response_class(response_data, **response_args)

serialize_response calls the default FastAPI jsonable_encoder meaning response_data has been encoded before the actual_response_class is invoked.

It seems like the recommendation in this thread is to explicitly return a custom Response inside each route – that does work, but it would be nice if we could just set a default_response_class when initializing FastAPI and call it a day.

Would it be possible to either:

  • pass raw_response as a kwarg to actual_response_class?
  • pass along a custom json encoder that would be called inside serialize_response?
6reactions
tangi75commented, Oct 2, 2020

Have the same issue. Did you solve it?

Only a PR would really solve it, provided it’s considered as an issue, hence my “question” here. Two possible workarounds:

  1. Explicit instantiation as illustrated above
  2. Tweak pydantic as suggested by @TTRh, e.g. pydantic.json.ENCODERS_BY_TYPE[datetime] = lambda dt: dt.replace(tzinfo=pytz.utc).isoformat()
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to write custom converters for JSON serialization - .NET
This article shows how to create custom converters for the JSON serialization classes that are provided in the System.Text.Json namespace.
Read more >
Failed to serialize the response in Web API with Json
I guess the xml serialiser can't serialise anonymous types and by removing it the result is serialised as json. If my guess is...
Read more >
Exposing a custom type as a JSON string in an ASP.NET Core ...
For instance, you can define a custom converter to control how values of a given type are serialized or deserialized. Simple enough, right?...
Read more >
Custom JSON Serialisation with System.Text.Json Converters
Text.Json. During serialisation, we can control this as I have done in the custom converter code above. We first get the actual type...
Read more >
JSON Serialization and Deserialization - GraphQL .NET
Two libraries are available for assistance deserializing JSON-formatted GraphQL requests, and serializing GraphQL responses in a JSON format.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found