Is there a way to pretty print / prettify a JSON response in FastAPI?
Question:
I’m looking for something that is similar to Flask’s app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
.
Answers:
I’m not sure what exactly your problem is, can you tell what the background of your need?
however, because FASTAPI is based on open standards(OpenAPI, JSONSchema) it has automatic docs. –>
FastAPI Auto Docs.
you have the Swagger UI under host/docs.
or the ReDoc under host/redoc.
Both will give you pretty representation of the JSON response in ease.
This is taken from David Montague.
You can annotate any endpoint with a custom response class, for example
@app.get("/config", response_class=PrettyJSONResponse)
def get_config() -> MyConfigClass:
return app.state.config
An example for PrettyJSONResponse
could be (indent=4
is what you were asking)
import json, typing
from starlette.responses import Response
class PrettyJSONResponse(Response):
media_type = "application/json"
def render(self, content: typing.Any) -> bytes:
return json.dumps(
content,
ensure_ascii=False,
allow_nan=False,
indent=4,
separators=(", ", ": "),
).encode("utf-8")
In order to avoid blocking the event loop for large lists of models, I ended up with a solution like the one below.
This should:
- Not block the event loop
- Stream results (much faster)
- Release event loop in between model dict actions
async def streaming_output_json(content: List[BaseModel]) -> StreamingResponse:
"""
Convert a list of Pydantic models to a JSON StreamingResponse.
"""
async def jsonify_async(models: List[BaseModel]) -> AsyncIterable[str]:
yield '['
for i, model in enumerate(models):
await asyncio.sleep(0)
if i > 0:
yield ','
result_dict = jsonable_encoder(model)
serialized_dict = json.dumps(result_dict)
yield serialized_dict
yield ']'
return StreamingResponse(jsonify_async(models=content), media_type='application/json')
@router.get("")
async def get_huge_result():
results = [model1, model2, ...]
return await streaming_output_json(results)
I’m looking for something that is similar to Flask’s app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
.
I’m not sure what exactly your problem is, can you tell what the background of your need?
however, because FASTAPI is based on open standards(OpenAPI, JSONSchema) it has automatic docs. –>
FastAPI Auto Docs.
you have the Swagger UI under host/docs.
or the ReDoc under host/redoc.
Both will give you pretty representation of the JSON response in ease.
This is taken from David Montague.
You can annotate any endpoint with a custom response class, for example
@app.get("/config", response_class=PrettyJSONResponse)
def get_config() -> MyConfigClass:
return app.state.config
An example for PrettyJSONResponse
could be (indent=4
is what you were asking)
import json, typing
from starlette.responses import Response
class PrettyJSONResponse(Response):
media_type = "application/json"
def render(self, content: typing.Any) -> bytes:
return json.dumps(
content,
ensure_ascii=False,
allow_nan=False,
indent=4,
separators=(", ", ": "),
).encode("utf-8")
In order to avoid blocking the event loop for large lists of models, I ended up with a solution like the one below.
This should:
- Not block the event loop
- Stream results (much faster)
- Release event loop in between model dict actions
async def streaming_output_json(content: List[BaseModel]) -> StreamingResponse:
"""
Convert a list of Pydantic models to a JSON StreamingResponse.
"""
async def jsonify_async(models: List[BaseModel]) -> AsyncIterable[str]:
yield '['
for i, model in enumerate(models):
await asyncio.sleep(0)
if i > 0:
yield ','
result_dict = jsonable_encoder(model)
serialized_dict = json.dumps(result_dict)
yield serialized_dict
yield ']'
return StreamingResponse(jsonify_async(models=content), media_type='application/json')
@router.get("")
async def get_huge_result():
results = [model1, model2, ...]
return await streaming_output_json(results)