Skip to main content

Using Alternative JSON Encoders

FastAPI provides specialized response classes for high-performance JSON serialization using the orjson and ujson libraries. While these were previously the recommended way to optimize JSON performance, they are now considered deprecated in modern FastAPI in favor of direct Pydantic serialization.

High-Performance Response Classes

The two primary alternative JSON encoders provided by FastAPI are ORJSONResponse and UJSONResponse, both located in fastapi.responses.

ORJSONResponse

ORJSONResponse uses the orjson library, which is often significantly faster than the standard Python json library. It is particularly useful when dealing with complex data types like NumPy arrays or non-string dictionary keys.

As defined in fastapi/responses.py, ORJSONResponse automatically enables specific orjson options:

class ORJSONResponse(JSONResponse):
def render(self, content: Any) -> bytes:
assert orjson is not None, "orjson must be installed to use ORJSONResponse"
return orjson.dumps(
content, option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY
)
  • OPT_NON_STR_KEYS: Allows serializing dictionaries with integer or other non-string keys.
  • OPT_SERIALIZE_NUMPY: Enables direct serialization of NumPy arrays.

UJSONResponse

UJSONResponse uses the ujson library. It is another high-performance alternative that focuses on speed and compatibility.

class UJSONResponse(JSONResponse):
def render(self, content: Any) -> bytes:
assert ujson is not None, "ujson must be installed to use UJSONResponse"
return ujson.dumps(content, ensure_ascii=False).encode("utf-8")

The implementation sets ensure_ascii=False by default, which can improve performance and reduce response size when dealing with non-ASCII characters.

Implementation via Protocols

To maintain type safety without forcing a hard dependency on these libraries, FastAPI defines internal protocols in fastapi/responses.py. These protocols, _OrjsonModule and _UjsonModule, describe the expected interface for the underlying libraries:

class _OrjsonModule(Protocol):
OPT_NON_STR_KEYS: int
OPT_SERIALIZE_NUMPY: int

def dumps(self, __obj: Any, *, option: int = ...) -> bytes: ...

class _UjsonModule(Protocol):
def dumps(self, __obj: Any, *, ensure_ascii: bool = ...) -> str: ...

Usage Patterns

You can apply these response classes either to specific routes or globally across your entire application.

Route-Specific Usage

To use an alternative encoder for a single path operation, use the response_class parameter in the decorator. This is demonstrated in docs_src/custom_response/tutorial001b_py310.py:

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"}]

Application-Wide Usage

If you want every route in your application to use a specific encoder by default, set the default_response_class in the FastAPI constructor. This pattern is frequently used in performance testing, such as in tests/test_orjson_response_class.py:

from fastapi import FastAPI
from fastapi.responses import ORJSONResponse

app = FastAPI(default_response_class=ORJSONResponse)

@app.get("/orjson_non_str_keys")
def get_orjson_non_str_keys():
# orjson handles non-string keys automatically
return {"msg": "Hello World", 1: 1}

Deprecation and Modern Alternatives

Both ORJSONResponse and UJSONResponse are marked as deprecated in the codebase. The docstrings in fastapi/responses.py explain the reasoning:

FastAPI now serializes data directly to JSON bytes via Pydantic when a return type or response model is set, which is faster and doesn't need a custom response class.

In modern FastAPI, if you define a response_model or use a return type hint, FastAPI uses Pydantic's optimized serialization logic to generate JSON bytes directly. This approach typically outperforms using a custom response class because it avoids the overhead of creating an intermediate Python dictionary before serialization.

Using these deprecated classes will trigger a FastAPIDeprecationWarning, as seen in tests/test_deprecated_responses.py:

@needs_orjson
def test_orjson_response_emits_deprecation_warning():
with pytest.warns(FastAPIDeprecationWarning, match="ORJSONResponse is deprecated"):
ORJSONResponse(content={"hello": "world"})

Requirements

Neither orjson nor ujson are included in the default FastAPI installation. If you choose to use these classes, you must install the libraries manually:

pip install orjson
# or
pip install ujson

If the library is not installed when the render method is called, FastAPI will raise an AssertionError with a descriptive message.