Files
xiaozhi-esp32-server/main/manager-api-fastapi/app/core/responses.py
T

67 lines
1.9 KiB
Python

from __future__ import annotations
import json
from typing import Any
from fastapi import Request
from starlette.responses import JSONResponse, Response
from app.core.i18n import message_for
from app.core.serialization import java_compatible
class JavaJSONResponse(JSONResponse):
def render(self, content: Any) -> bytes:
return json.dumps(
java_compatible(content),
ensure_ascii=False,
allow_nan=False,
separators=(",", ":"),
).encode("utf-8")
def envelope(data: Any = None, *, code: int = 0, msg: str = "success") -> dict[str, Any]:
return {"code": code, "msg": msg, "data": data}
def ok(data: Any = None) -> JavaJSONResponse:
return JavaJSONResponse(envelope(data))
def error_response(
request: Request,
code: int,
message: str | None = None,
*,
status_code: int = 200,
params: tuple[object, ...] = (),
media_type: str = "application/json",
) -> JavaJSONResponse:
translated = message or message_for(code, request.headers.get("Accept-Language"), *params)
return JavaJSONResponse(
envelope(None, code=code, msg=translated),
status_code=status_code,
media_type=media_type,
)
def raw_json(content: Any, *, exclude_none: bool = False, status_code: int = 200) -> Response:
normalized = java_compatible(content)
if exclude_none:
normalized = _drop_none(normalized)
body = json.dumps(normalized, ensure_ascii=False, allow_nan=False, separators=(",", ":")).encode("utf-8")
return Response(
body,
status_code=status_code,
media_type="application/json",
headers={"Content-Length": str(len(body))},
)
def _drop_none(value: Any) -> Any:
if isinstance(value, dict):
return {key: _drop_none(item) for key, item in value.items() if item is not None}
if isinstance(value, list):
return [_drop_none(item) for item in value]
return value