Reading request
data using orjson
When calling await request.json()
, FastAPI (actually Starlette) first reads the body (using the .body()
method of the Request
object), and then calls json.loads()
(using the standard json
library of Python) to return a dict
/list
object to you inside the endpoint (see the implementation here)—it doesn't use .dumps()
, as you mentioned in the comments section, as that method is used to serialise a Python object into JSON.
Hence, to read/convert the request body using orjson
instead, you can use the below (if you would like to retrieve the raw body within a def
instead of async def
endpoint, please have a look at this answer):
from fastapi import FastAPI, Request
import orjson
app = FastAPI()
@app.post('/')
async def submit(request: Request):
body = await request.body()
data = orjson.loads(body)
return 'success'
Returning response
data using orjson
When returning data such as dict
, list
, etc, FastAPI will automatically convert that return value into JSON, using the Python standard json.dumps()
, after inspecting every item inside and making sure it is serializable with JSON, using the JSON Compatible Encoder (see this answer for more details). Hence, if you would like to use the orjson
library instead, you would need to send a custom Response
directly, as described in this answer. Example:
from fastapi import FastAPI, Request
import orjson
app = FastAPI()
@app.post('/')
async def submit(request: Request):
body = await request.body()
data = orjson.loads(body)
return Response(orjson.dumps(data), media_type='application/json')
Returning response
data using FastAPI's ORJSONResponse
Alternatively, you could use the ORJSONResponse
provided by FastAPI (still make sure you have the orjson
libray installed, as well as the content that you are returning is serializable with JSON). Have a look at futher documentation here and here on how to customise and/or set ORJSONResponse
as the default response class (the implementation of the ORJSONResponse
could be found here).
Note that when using the response_class
parameter in the endpoint's decorator to set the Response
class, one does not necessarily need to use that response class when returning the data from the endpoint as well. This is because FastAPI, behind the scenes, will encode/serialise the data based on the response_class
you set, as well as use it to define the "media type" of the response. Hence, one could either set response_class=ORJSONResponse
or return ORJSONResponse(...)
. Having said that, it wouldn't hurt using both, as shown in the example below and in some examples provided in the official FastAPI documentation, not only for clarity purposes, but also for proper Swagger UI documentation purposes. The response_class
will inform Swagger UI/OpenAPI docs for the expected media type of a successful response—one could confirm that by looking at the expected "Responses" and their media type under an endpoint in /docs
(see FastAPI's documentation for declaring additional responses in OpenAPI).
from fastapi import FastAPI, Request
from fastapi.responses import ORJSONResponse
app = FastAPI()
@app.post('/', response_class=ORJSONResponse)
async def submit(request: Request):
body = await request.body()
return ORJSONResponse(body.decode('utf-8'))
In the case of the example above, one wouldn't notice any difference in Swagger UI autodocs whether or not using the response_class=ORJSONResponse
, as application/json
is the default media type for FastAPI endpoints, regardless. However, in a follwoing example in this answer, where HTMLResponse
is returned from a specific endpoint, if one didn't use response_class=HTMLResponse
, Swagger UI/OpenAPI docs would incorrectly indicate that an application/json
response is expected from that endpoint in case of a successful response.
Setting ORJSONResponse
as the default_response_class
As explained in the documentation, one can define the default response class for their FastAPI application, as follows. In that way, every response from FastAPI will be encoded using ORJSONResponse
in the example below; thus, there would be no need for you to either set response_class=ORJSONResponse
or use return ORJSONResponse(...)
.
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
app = FastAPI(default_response_class=ORJSONResponse)
@app.get("/items")
async def read_items():
return [{"item_id": "Foo"}]
You will still be able to override the default response class in an endpoint if needed, as shown in the examples earlier, by either setting the response_class
parameter in the endpoint's decorator or returning that Response
class directly, or using both methods, as explained earlier, so that Swagger UI/OpenAPI documentation is informed for the expected response type of that endpoint. For instance:
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse, HTMLResponse
app = FastAPI(default_response_class=ORJSONResponse)
@app.get("/items")
async def read_items():
return [{"item_id": "Foo"}]
@app.get("/html", response_class=HTMLResponse)
async def get_html():
html_content = """
<html>
<body>
<h1>HTML!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
Please make sure to have a look here, here, as well as here and here to learn about the various approaches of sending JSON data to a FastAPI backend, and how to define an endpoint to expect and validate JSON data, instead of relying on using await request.json()
(which is useful when the app requires passing arbitrary JSON data, but does not perform any validation on the data).
request.json
, it was usedjson.dumps()
, I wanna replace it with orgjson package. – Gath