Remove UJSONResponse (#1047)

* Remove UJSONResponse

* Add documentation about custom JSON serialization
This commit is contained in:
Jamie Hewland 2020-11-08 22:49:12 +02:00 committed by GitHub
parent 8bfc2a3c26
commit 99b37781eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 16 additions and 44 deletions

View File

@ -95,7 +95,6 @@ Starlette does not have any hard dependencies, but the following are optional:
* [`itsdangerous`][itsdangerous] - Required for `SessionMiddleware` support.
* [`pyyaml`][pyyaml] - Required for `SchemaGenerator` support.
* [`graphene`][graphene] - Required for `GraphQLApp` support.
* [`ujson`][ujson] - Required if you want to use `UJSONResponse`.
You can install all of these with `pip3 install starlette[full]`.
@ -140,7 +139,6 @@ as [one of the fastest Python frameworks available](https://www.techempower.com/
For high throughput loads you should:
* Make sure to install `ujson` and use `UJSONResponse`.
* Run using gunicorn using the `uvicorn` worker class.
* Use one or two workers per-CPU core. (You might need to experiment with this.)
* Disable access logging.
@ -178,4 +176,3 @@ gunicorn -k uvicorn.workers.UvicornH11Worker ...
[itsdangerous]: https://pythonhosted.org/itsdangerous/
[sqlalchemy]: https://www.sqlalchemy.org
[pyyaml]: https://pyyaml.org/wiki/PyYAMLDocumentation
[ujson]: https://github.com/esnme/ultrajson

View File

@ -89,7 +89,6 @@ Starlette does not have any hard dependencies, but the following are optional:
* [`itsdangerous`][itsdangerous] - Required for `SessionMiddleware` support.
* [`pyyaml`][pyyaml] - Required for `SchemaGenerator` support.
* [`graphene`][graphene] - Required for `GraphQLApp` support.
* [`ujson`][ujson] - Required if you want to use `UJSONResponse`.
You can install all of these with `pip3 install starlette[full]`.
@ -134,7 +133,6 @@ as [one of the fastest Python frameworks available](https://www.techempower.com/
For high throughput loads you should:
* Make sure to install `ujson` and use `UJSONResponse`.
* Run using Gunicorn using the `uvicorn` worker class.
* Use one or two workers per-CPU core. (You might need to experiment with this.)
* Disable access logging.
@ -172,4 +170,3 @@ gunicorn -k uvicorn.workers.UvicornH11Worker ...
[itsdangerous]: https://pythonhosted.org/itsdangerous/
[sqlalchemy]: https://www.sqlalchemy.org
[pyyaml]: https://pyyaml.org/wiki/PyYAMLDocumentation
[ujson]: https://github.com/esnme/ultrajson

View File

@ -92,26 +92,30 @@ async def app(scope, receive, send):
await response(scope, receive, send)
```
### UJSONResponse
#### Custom JSON serialization
A JSON response class that uses the optimised `ujson` library for serialisation.
If you need fine-grained control over JSON serialization, you can subclass
`JSONResponse` and override the `render` method.
Using `ujson` will result in faster JSON serialisation, but is also less careful
than Python's built-in implementation in how it handles some edge-cases.
In general you *probably* want to stick with `JSONResponse` by default unless
you are micro-optimising a particular endpoint.
For example, if you wanted to use a third-party JSON library such as
[orjson](https://pypi.org/project/orjson/):
```python
from starlette.responses import UJSONResponse
from typing import Any
import orjson
from starlette.responses import JSONResponse
async def app(scope, receive, send):
assert scope['type'] == 'http'
response = UJSONResponse({'hello': 'world'})
await response(scope, receive, send)
class OrjsonResponse(JSONResponse):
def render(self, content: Any) -> bytes:
return orjson.dumps(content)
```
In general you *probably* want to stick with `JSONResponse` by default unless
you are micro-optimising a particular endpoint or need to serialize non-standard
object types.
### RedirectResponse
Returns an HTTP redirect. Uses a 307 status code by default.

View File

@ -6,7 +6,6 @@ jinja2
python-multipart
pyyaml
requests
ujson
# Testing
autoflake

View File

@ -57,7 +57,6 @@ setup(
"python-multipart",
"pyyaml",
"requests",
"ujson",
]
},
classifiers=[

View File

@ -24,11 +24,6 @@ except ImportError: # pragma: nocover
aiofiles = None # type: ignore
aio_stat = None # type: ignore
try:
import ujson
except ImportError: # pragma: nocover
ujson = None # type: ignore
# Compatibility wrapper for `mimetypes.guess_type` to support `os.PathLike` on <py3.8
def guess_type(
@ -172,14 +167,6 @@ class JSONResponse(Response):
).encode("utf-8")
class UJSONResponse(JSONResponse):
media_type = "application/json"
def render(self, content: typing.Any) -> bytes:
assert ujson is not None, "ujson must be installed to use UJSONResponse"
return ujson.dumps(content, ensure_ascii=False).encode("utf-8")
class RedirectResponse(Response):
def __init__(
self,

View File

@ -12,7 +12,6 @@ from starlette.responses import (
RedirectResponse,
Response,
StreamingResponse,
UJSONResponse,
)
from starlette.testclient import TestClient
@ -37,16 +36,6 @@ def test_bytes_response():
assert response.content == b"xxxxx"
def test_ujson_response():
async def app(scope, receive, send):
response = UJSONResponse({"hello": "world"})
await response(scope, receive, send)
client = TestClient(app)
response = client.get("/")
assert response.json() == {"hello": "world"}
def test_json_none_response():
async def app(scope, receive, send):
response = JSONResponse(None)