5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

responderでjsonを返す際に日本語をUnicodeエスケープさせない

Last updated at Posted at 2019-01-21

※ 訂正
文字化けではなく、Unicodeエスケープが正しい表現です。
コメント欄をご確認ください。
記事内容を修正予定ではありますが、取り急ぎ。

記事概要

responder on dockerしようとしたら、hello worldできなくて焦った話 に引き続き、responderです。

プロ野球選手の名前をjsonで返すAPIを実装した際に、日本語のUnicodeエスケープを解消したチップスです。

ドキュメントに沿って実装したけど、Unicodeエスケープされた

実装

result[0] = {'name': '淺間 大基'}
resp.media = result[0]

ブラウザでの表示

スクリーンショット 2019-01-21 9.57.50.png

やっぱりこういう時、日本人だなーって思いますね :sushi:

解消方法

実装

resp.headers = {"Content-Type": "application/json; charset=utf-8"}
resp.content = json.dumps(result[0], ensure_ascii=False)

ブラウザでの表示

スクリーンショット 2019-01-21 10.02.16.png

上記で良いと思うのですが、いかがでしょうか。

responseクラスに関して

ようするに、

  • asciiに限定したエンコードをしない
  • jsonに変換する
  • Content-Typeのcharset=utf-8

を満たす実装が必要なわけです。

responseクラスの実装を見た感じだと、先程示した実装で良いと思うですがいかがでしょうか。

class Response:
    __slots__ = [
        "req",
        "status_code",
        "text",
        "content",
        "encoding",
        "media",
        "headers",
        "formats",
        "cookies",
        "session",
    ]

    def __init__(self, req, *, formats):
        self.req = req
        self.status_code = None  #: The HTTP Status Code to use for the Response.
        self.text = None  #: A unicode representation of the response body.
        self.content = None  #: A bytes representation of the response body.
        self.encoding = DEFAULT_ENCODING
        self.media = (
            None
        )  #: A Python object that will be content-negotiated and sent back to the client. Typically, in JSON formatting.
        self.headers = (
            {}
        )  #: A Python dictionary of ``{key: value}``, representing the headers of the response.
        self.formats = formats
        self.cookies = {}  #: The cookies set in the Response, as a dictionary
        self.session = (
            req.session.copy()
        )  #: The cookie-based session data, in dict form, to add to the Response.

    @property
    async def body(self):
        if self.content is not None:
            return (self.content, {})

        if self.text is not None:
            return (self.text.encode(self.encoding), {"Encoding": self.encoding})

        for format in self.formats:
            if self.req.accepts(format):
                return (await self.formats[format](self, encode=True)), {}

        # Default to JSON anyway.
        return (
            await self.formats["json"](self, encode=True),
            {"Content-Type": "application/json"},
        )

    async def __call__(self, receive, send):
        body, headers = await self.body
        if self.headers:
            headers.update(self.headers)

        response = StarletteResponse(
            body, status_code=self.status_code, headers=headers
        )
        await response(receive, send)

以上。問題あればご指摘ください!

5
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?