fastapi icon indicating copy to clipboard operation
fastapi copied to clipboard

FastAPI don't call pydantic to json

Open samsja opened this issue 2 years ago • 5 comments

First Check

  • [X] I added a very descriptive title to this issue.
  • [X] I used the GitHub search to find a similar issue and didn't find it.
  • [X] I searched the FastAPI documentation, with the integrated search.
  • [X] I already searched in Google "How to X in FastAPI" and didn't find any information.
  • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [X] I already checked if it is not related to FastAPI but to Pydantic.
  • [X] I already checked if it is not related to FastAPI but to Swagger UI.
  • [X] I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • [X] I commit to help with one of those options 👆

Example Code

import json

from fastapi import FastAPI
from pydantic import BaseModel


def json_dump(*args, **kwargs):
    print('HELLO')
    return json.dumps(*args, **kwargs)

class MyModel(BaseModel):

    class Config:
        json_dumps = json_dump

    a : int


data = MyModel(a=1)

data.json()

app = FastAPI()

@app.post("/hello/", response_model=MyModel)
async def hello() -> MyModel:
    return MyModel(a=1)


import uvicorn

uvicorn.run(app)

### on client.py side
from httpx import Client

with Client(base_url="http://localhost:8000") as ac:
    resp = ac.post(
        "/hello/",
    )

>>> HELLO

Description

This shows the HELLO is called only once. Which means FastAPI is not using the pydantic to json function.

By looking at the code we can see that there is a custom function written on FastAPI side. Is there a way to use the json method from pydantic instead ?

Thanks in advance

Operating System

Linux

Operating System Details

No response

FastAPI Version

0.87.0

Python Version

3.9.10

Additional Context

No response

samsja avatar Jan 09 '23 16:01 samsja

I think you could use def dict in Pydantic. FastAPI uses jsonable_encoder to create a dict from a Pydantic model then serializes the result with json, orjson, ujson etc

odiseo0 avatar Jan 09 '23 20:01 odiseo0

you can set json_encoders in pydantic model instead of json_dumps for example: json_encoders = {float: lambda x: float(x)}

yinziyan1206 avatar Jan 10 '23 02:01 yinziyan1206

Yes indeed json_encoders is a way to do it. Unfortunately it will be called not directly on the BaseModel but at its child levels. In the code it first goes into the BaseModel collect the json encoder and then call it but only on the child.

My question is why not using directly BaseModel.json() in FastAPI ? There might be a reason that I am not aware like something related to SQLAlchemy. But from what I saw it looks like a redundancy with pydantic code

samsja avatar Jan 10 '23 08:01 samsja

let

I think you could use def dict in Pydantic. FastAPI uses jsonable_encoder to create a dict from a Pydantic model then serializes the result with json, orjson, ujson etc

Let me check if I can solve my problem with this. Thanks for the feedback

samsja avatar Jan 10 '23 08:01 samsja

I found out a solution with json_encoder but I still wondering why not just use BaseModel.json() from pydantic

samsja avatar Jan 10 '23 15:01 samsja