When you do json.dumps
, that will convert your dict
object into a string. Then, you are passing that string to the Sanic response.json
, which also under the hood performs a json.dumps
like call.
Therefore, you are essentially serializing your data twice.
async def test(request):
output = {'hello': 'world'}
return response.json(output)
When I hit this endpoint, I get JSON as expected:
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: 5
Content-Length: 17
Content-Type: application/json
{"hello":"world"}
If I wrap it in json.dumps
:
@app.route('/')
async def test(request):
output = json.dumps({'hello': 'world'})
return response.json(output)
I get an unintended result:
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: 5
Content-Length: 24
Content-Type: application/json
"{\"hello\": \"world\"}"
This explains why … but it does not explain how you can achieve your goal of customizing the serialization method.
Luckily, the response.json
method takes a dumps
keyword, which is the function that will perform the serializing. So, if I need to make a modification to the serializing method (as in your case with ensure_ascii=False
), then I can do it like this:
from functools import partial
@app.route('/')
async def test(request):
output = {'hello': 'world'}
dumps = partial(json.dumps, ensure_ascii=False)
return response.json(output, dumps=dumps)
And, using your example, the response:
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: 5
Content-Length: 139
Content-Type: application/json
[{"eng_name": "moskva", "rus_name": "Москва"}, {"eng_name": "adygeya_resp", "rus_name": "Адыгейская республика"}]