From 58898a729ccc93382073150134348b516195feb7 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 10 Oct 2018 17:04:12 +0100 Subject: [PATCH] Add explicit UJSONResponse (#99) --- starlette/responses.py | 35 ++++++++++++++++++++--------------- tests/test_responses.py | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/starlette/responses.py b/starlette/responses.py index 7b34ec67..83f7f978 100644 --- a/starlette/responses.py +++ b/starlette/responses.py @@ -5,6 +5,7 @@ from starlette.datastructures import MutableHeaders, URL from starlette.types import Receive, Send from urllib.parse import quote_plus import hashlib +import json import os import typing import http.cookies @@ -13,22 +14,13 @@ try: import aiofiles from aiofiles.os import stat as aio_stat except ImportError: # pragma: nocover - aiofiles = None - aio_stat = None + aiofiles = None # type: ignore + aio_stat = None # type: ignore try: - import ujson as json - - JSON_DUMPS_OPTIONS = {"ensure_ascii": False} + import ujson except ImportError: # pragma: nocover - import json - - JSON_DUMPS_OPTIONS = { - "ensure_ascii": False, - "allow_nan": False, - "indent": None, - "separators": (",", ":"), - } + ujson = None # type: ignore class Response: @@ -57,7 +49,7 @@ class Response: def init_headers(self, headers) -> None: if headers is None: - raw_headers = [] + raw_headers = [] # type: typing.List[typing.Tuple[bytes, bytes]] populate_content_length = True populate_content_type = True else: @@ -145,7 +137,20 @@ class JSONResponse(Response): media_type = "application/json" def render(self, content: typing.Any) -> bytes: - return json.dumps(content, **JSON_DUMPS_OPTIONS).encode("utf-8") + return json.dumps( + content, + ensure_ascii=False, + allow_nan=False, + indent=None, + separators=(",", ":"), + ).encode("utf-8") + + +class UJSONResponse(JSONResponse): + media_type = "application/json" + + def render(self, content: typing.Any) -> bytes: + return ujson.dumps(content, ensure_ascii=False).encode("utf-8") class RedirectResponse(Response): diff --git a/tests/test_responses.py b/tests/test_responses.py index 5cdc6e12..cca991b4 100644 --- a/tests/test_responses.py +++ b/tests/test_responses.py @@ -3,6 +3,7 @@ from starlette.responses import ( RedirectResponse, Response, StreamingResponse, + UJSONResponse, ) from starlette.requests import Request from starlette.testclient import TestClient @@ -36,6 +37,19 @@ def test_bytes_response(): assert response.content == b"xxxxx" +def test_ujson_response(): + def app(scope): + async def asgi(receive, send): + response = UJSONResponse({"hello": "world"}) + await response(receive, send) + + return asgi + + client = TestClient(app) + response = client.get("/") + assert response.json() == {"hello": "world"} + + def test_redirect_response(): def app(scope): async def asgi(receive, send):