Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

記事概要

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

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

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

https://python-responder.org/en/latest/quickstart.html#returning-json-yaml

実装

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クラスの実装を見た感じだと、先程示した実装で良いと思うですがいかがでしょうか。

https://python-responder.org/en/latest/_modules/responder/models.html#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)

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

nassy20
201807 ~ Python webエンジニア; 内容が間違っていたらご指摘ください;
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away