Browse Source

Add ORJSONResponse (#1065)

*  Add ORJSONResponse

* 📝 Add tutorial using ORJSONResponse

*  Add test for ORJSONResponse

* 📝 Update index.md
pull/1068/head
Sebastián Ramírez 5 years ago
committed by GitHub
parent
commit
94ee932351
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      README.md
  2. 22
      docs/advanced/custom-response.md
  3. 1
      docs/index.md
  4. 9
      docs/src/custom_response/tutorial001b.py
  5. 15
      fastapi/responses.py
  6. 36
      tests/test_tutorial/test_custom_response/test_tutorial001b.py

1
README.md

@ -398,6 +398,7 @@ Used by Starlette:
Used by FastAPI / Starlette: Used by FastAPI / Starlette:
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application. * <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
You can install all of these with `pip install fastapi[all]`. You can install all of these with `pip install fastapi[all]`.

22
docs/advanced/custom-response.md

@ -13,14 +13,14 @@ And if that `Response` has a JSON media type (`application/json`), like is the c
!!! note !!! note
If you use a response class with no media type, FastAPI will expect your response to have no content, so it will not document the response format in its generated OpenAPI docs. If you use a response class with no media type, FastAPI will expect your response to have no content, so it will not document the response format in its generated OpenAPI docs.
## Use `UJSONResponse` ## Use `ORJSONResponse`
For example, if you are squeezing performance, you can install and use `ujson` and set the response to be `UJSONResponse`. For example, if you are squeezing performance, you can install and use <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> and set the response to be `ORJSONResponse`.
Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*. Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
```Python hl_lines="2 7" ```Python hl_lines="2 7"
{!./src/custom_response/tutorial001.py!} {!./src/custom_response/tutorial001b.py!}
``` ```
!!! info !!! info
@ -30,6 +30,9 @@ Import the `Response` class (sub-class) you want to use and declare it in the *p
And it will be documented as such in OpenAPI. And it will be documented as such in OpenAPI.
!!! tip
The `ORJSONResponse` is currently only available in FastAPI, not in Starlette.
## HTML Response ## HTML Response
To return a response with HTML directly from **FastAPI**, use `HTMLResponse`. To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
@ -134,13 +137,24 @@ Takes some data and returns an `application/json` encoded response.
This is the default response used in **FastAPI**, as you read above. This is the default response used in **FastAPI**, as you read above.
### `ORJSONResponse`
A fast alternative JSON response using <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, as you read above.
### `UJSONResponse` ### `UJSONResponse`
An alternative JSON response using `ujson` for faster serialization as you read above. An alternative JSON response using <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
!!! warning !!! warning
`ujson` is less careful than Python's built-in implementation in how it handles some edge-cases. `ujson` is less careful than Python's built-in implementation in how it handles some edge-cases.
```Python hl_lines="2 7"
{!./src/custom_response/tutorial001.py!}
```
!!! tip
It's possible that `ORJSONResponse` might be a faster alternative.
### `RedirectResponse` ### `RedirectResponse`
Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default. Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default.

1
docs/index.md

@ -398,6 +398,7 @@ Used by Starlette:
Used by FastAPI / Starlette: Used by FastAPI / Starlette:
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application. * <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
You can install all of these with `pip install fastapi[all]`. You can install all of these with `pip install fastapi[all]`.

9
docs/src/custom_response/tutorial001b.py

@ -0,0 +1,9 @@
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
app = FastAPI()
@app.get("/items/", response_class=ORJSONResponse)
async def read_items():
return [{"item_id": "Foo"}]

15
fastapi/responses.py

@ -1,3 +1,5 @@
from typing import Any
from starlette.responses import FileResponse # noqa from starlette.responses import FileResponse # noqa
from starlette.responses import HTMLResponse # noqa from starlette.responses import HTMLResponse # noqa
from starlette.responses import JSONResponse # noqa from starlette.responses import JSONResponse # noqa
@ -6,3 +8,16 @@ from starlette.responses import RedirectResponse # noqa
from starlette.responses import Response # noqa from starlette.responses import Response # noqa
from starlette.responses import StreamingResponse # noqa from starlette.responses import StreamingResponse # noqa
from starlette.responses import UJSONResponse # noqa from starlette.responses import UJSONResponse # noqa
try:
import orjson
except ImportError: # pragma: nocover
orjson = None # type: ignore
class ORJSONResponse(JSONResponse):
media_type = "application/json"
def render(self, content: Any) -> bytes:
assert orjson is not None, "orjson must be installed to use ORJSONResponse"
return orjson.dumps(content)

36
tests/test_tutorial/test_custom_response/test_tutorial001b.py

@ -0,0 +1,36 @@
from fastapi.testclient import TestClient
from custom_response.tutorial001b import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
"summary": "Read Items",
"operationId": "read_items_items__get",
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200
assert response.json() == openapi_schema
def test_get_custom_response():
response = client.get("/items/")
assert response.status_code == 200
assert response.json() == [{"item_id": "Foo"}]
Loading…
Cancel
Save