Source code for loom.rest.fastapi.response

"""MsgspecJSONResponse — zero-copy JSON response for FastAPI.

Uses ``msgspec.json.encode`` to serialise response content directly to bytes,
bypassing the stdlib ``json`` module and Pydantic's serialisation pipeline.
No double-serialisation occurs: the bytes are written to the response body
exactly once.

Supports any type that ``msgspec.json.encode`` accepts: plain Python types
(``dict``, ``list``, ``str``, ``int``, etc.), ``msgspec.Struct`` instances,
and ``dataclasses``.

Usage::

    from loom.rest.fastapi.response import MsgspecJSONResponse

    @app.get("/items/{item_id}")
    async def get_item(item_id: int) -> MsgspecJSONResponse:
        item = await repo.get(item_id)
        return MsgspecJSONResponse(content=item)
"""

from __future__ import annotations

import msgspec
from starlette.responses import Response


[docs] class MsgspecJSONResponse(Response): """FastAPI ``Response`` subclass that encodes content with ``msgspec.json``. Drop-in replacement for ``fastapi.responses.JSONResponse`` with two advantages: - Native ``msgspec.Struct`` serialisation — no ``dict`` conversion needed. - Single encoding pass — content is written directly to bytes with no intermediate JSON string or Pydantic round-trip. Args: content: Any object supported by ``msgspec.json.encode``. status_code: HTTP status code. Defaults to ``200``. headers: Additional response headers. media_type: Defaults to ``"application/json"``. background: Optional Starlette background task. Example:: return MsgspecJSONResponse(content=my_struct, status_code=201) """ media_type = "application/json"
[docs] def render(self, content: object) -> bytes: """Encode ``content`` to JSON bytes using ``msgspec.json.encode``. Args: content: Object to serialise. Returns: UTF-8 encoded JSON bytes. """ return msgspec.json.encode(content)