※ 訂正
文字化けではなく、Unicodeエスケープが正しい表現です。
コメント欄をご確認ください。
記事内容を修正予定ではありますが、取り急ぎ。
記事概要
responder on dockerしようとしたら、hello worldできなくて焦った話 に引き続き、responderです。
プロ野球選手の名前をjsonで返すAPIを実装した際に、日本語のUnicodeエスケープを解消したチップスです。
ドキュメントに沿って実装したけど、Unicodeエスケープされた
実装
result[0] = {'name': '淺間 大基'}
resp.media = result[0]
ブラウザでの表示
やっぱりこういう時、日本人だなーって思いますね
解消方法
実装
resp.headers = {"Content-Type": "application/json; charset=utf-8"}
resp.content = json.dumps(result[0], ensure_ascii=False)
ブラウザでの表示
上記で良いと思うのですが、いかがでしょうか。
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)
以上。問題あればご指摘ください!