Why sanic return response as text?


#1

Next code:

    def request_processing(req):
        answer = json.dumps(get_db_regions(), ensure_ascii=False)
        return response.json(answer)

JS typeof show data type as text

is return to web-browser text instead of json-object. What’s wrong? How I can fix it?

But this code is return correct json:

return response.json([{"eng_name": "moskva", "rus_name": "Москва"}, {"eng_name": "adygeya_resp", "rus_name": "Адыгейская республика"}])

UPD:

this code is return correct json:

return response.json(get_db_regions())

Why? Response convert any answer to json? Who can explain?


#2

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": "Адыгейская республика"}]