Replies: 14 comments
-
When fetching data that's been pre-encoded in JSON, I generally create a custom response class to skip JSON encoding and validation completely. FastAPI will acknowledge from starlette.responses import JSONResponse
class RawJSONResponse(JSONResponse):
def render(self, content: bytes) -> bytes:
return content
@get("/foo", response_model=MyModel, response_class=RawJSONResponse)
def foo():
return """{"raw": "json"}""" The problem I'm seeing here is that you don't get "raw" json from the DB, you get individual JSON elements that still need to be assembled together. What you could always do is use Postgres' SELECT json_array_agg(json_build_object('id', id, 'data', data)) FROM mytable WHERE id=5 I don't know how hard that would be to acheive in ORM mode, though. |
Beta Was this translation helpful? Give feedback.
-
fastest I achieved is with orjson and transforming my request to json in postgresql, you can do that with something like
|
Beta Was this translation helpful? Give feedback.
-
@euri10: I can't imagine why the |
Beta Was this translation helpful? Give feedback.
-
I think you're right and that you could directly dump into json
https://magicstack.github.io/asyncpg/current/usage.html?highlight=json#example-automatic-json-conversion
Le jeu. 12 déc. 2019 à 8:37 PM, sm-Fifteen <notifications@github.com> a
écrit :
… @euri10 <https://github.com/euri10>: I can't imagine why the
json.loadstring before re-encoding with osjson would be necessary, unless
you're doing that to not skip the validation step, but then I'm not really
seeing any benefit to making Postgres handle the JSON encoding instead of
just returning your data as rows. Is there anything I'm missing?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#788>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAINSPQUKHGCNHS4UM6RS6TQYKHGZANCNFSM4J2ATMGQ>
.
|
Beta Was this translation helpful? Give feedback.
-
Thanks, I'll change my code to what you showed me 👍 |
Beta Was this translation helpful? Give feedback.
-
I was able to fetch a complete json
I used this strategy and it is now really fast 🎊 But now I can't use |
Beta Was this translation helpful? Give feedback.
-
Are you sure? Setting |
Beta Was this translation helpful? Give feedback.
-
Apparently I am doing something wrong because fastapi is not skipping validation with your solution. When I run your code exactly like this: from starlette.responses import JSONResponse
import pydantic
class CustomJson(JSONResponse):
def render(self, content: bytes) -> bytes:
return content
class Item(pydantic.BaseModel):
id: int
@app.get("/foo", response_model=Item, response_class=CustomJson)
def foo():
return """{"raw": "json"}""" I get this error: File "...\lib\site-packages\fastapi\routing.py", line 72, in serialize_response
raise ValidationError(errors, field.type_)
pydantic.error_wrappers.ValidationError: 1 validation error for Item
response
value is not a valid dict (type=type_error.dict) |
Beta Was this translation helpful? Give feedback.
-
Apparently, response_class is not actually doing anything so I have to manually create the from starlette.responses import JSONResponse
import pydantic
class CustomJson(JSONResponse):
def render(self, content: bytes) -> bytes:
return content
class Item(pydantic.BaseModel):
id: int
@app.get("/foo", response_model=Item)
def foo():
return CustomJson("""{"raw": "json"}""") |
Beta Was this translation helpful? Give feedback.
-
@littlebrat This isn't a bug -- FastAPI first takes your return value, then converts it into the specified The idea is that the custom response class should expect to receive a model, rather than raw bytes. You can see the logic for this here:https://github.com/tiangolo/fastapi/blob/7a445402d4960d6173d76dac43393ad6c5040521/fastapi/routing.py#L126-L146 Currently, you can get around this by manually returning the response class, which short circuits any processing. (You could put this into a small decorator if you want easier reusability.) If you think there is a gap about this in the documentation, a PR would be welcome! Also, if you think the behavior should be different, feel free to open a feature request issue. |
Beta Was this translation helpful? Give feedback.
-
No, you're right, I forgot about that part, my bad. You actually need to return a pre-instanciated Response object. |
Beta Was this translation helpful? Give feedback.
-
Thanks everyone for the help here! 🚀 🍰 Does that solve it for you @littlebrat ? |
Beta Was this translation helpful? Give feedback.
-
Sorry for the delay, yes it did! |
Beta Was this translation helpful? Give feedback.
-
Thanks for reporting back @littlebrat ! 🚀 |
Beta Was this translation helpful? Give feedback.
-
First check
I used the GitHub search to find a similar issue and didn't find it.
Provide timing data for things FastAPI does outside of user code #701 (comment)
I searched the FastAPI documentation, with the integrated search.
I already searched in Google "How to X in FastAPI" and didn't find any information.
Description
I am dealing with JSON data in the order of 10 MBs (up to hundred MBs) which I directly get from a Postgres Instance.
This data is stored as JSONB on this database. To fetch this large amount of data without parsing it into a dictionary I do the following:
Since I know this data has been properly validated when it was inserted I just use the construct factory from pydantic:
Then, on the endpoint I directly return a response using:
But, I still describe the response_model as List[Item] as I need the documentation for this endpoint.
Using this strategy I am able to achieve really good response times, though the original JSON data is encoded now as a string and not as an object when decoded.
So the clients of the API have to decode the response many times:
1) The request itself
2) Once for each JSON object retrieved
Is there any good practice on how to tackle this problem?
Beta Was this translation helpful? Give feedback.
All reactions