この記事は最終更新日から1年以上が経過しています。
HTTP の レスポンスヘッダー を json.dumps しようと思いはまったので記事を書いてみました。
単純にレスポンスの結果を表示してみる。
import requests req = requests.get(url='http://example.com') print(req.headers) |
実行結果
{'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '11', 'Server': 'Werkzeug/0.14.1 Python/3.6.4', 'Date': 'Thu, 08 Mar 2018 10:13:52 GMT'} |
正常に動作したのでJSONで出力してみる。
json.dumps で出力できるはず。
import requests, json req = requests.get(url='http://example.com') print(json.dumps(req.headers)) |
実行結果
Traceback (most recent call last): File "test.py", line 7, in <module> print(json.dumps(req.headers)) File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default o.__class__.__name__) TypeError: Object of type 'CaseInsensitiveDict' is not JSON serializable |
なんでや!!なんでなんや!!
CaseInsensitiveDict は JSON serializable できないと怒られています。
requests.response.headers はただのdictではなくCaseInsensitiveDict という型で 、json.dumps に対応していない型らしい。
型をdictにするとうまくいく。
import requests, json req = requests.get(url='http://example.com') print(json.dumps(dict(req.headers))) |
実行結果
{"Content-Encoding": "gzip", "Accept-Ranges": "bytes", "Cache-Control": "max-age=604800", "Content-Type": "text/html", "Date": "Thu, 08 Mar 2018 10:23:24 GMT", "Etag": "\"1541025663+gzip\"", "Expires": "Thu, 15 Mar 2018 10:23:24 GMT", "Last-Modified": "Fri, 09 Aug 2013 23:54:35 GMT", "Server": "ECS (pae/3796)", "Vary": "Accept-Encoding", "X-Cache": "HIT", "Content-Length": "606"} |
なぜこんなことをするのか…
API Gateway から Lambda 実行した際に response は以下の形式の辞書型を返します。
{ 'statusCode': statusCode, 'headers': headers , 'body': body } |
requests.response の結果をただ返すと、Lambda の方で 関数の response を json.dumps しているようで、return した後に同様のエラーに遭遇します。
An error occurred during JSON serialization of response: {'Content-Encoding': 'gzip', 'Content-Type': 'application/json;charset=UTF-8', 'Date': 'Thu, 08 Mar 2018 09:21:06 GMT', 'Server': 'Apache-Coyote/1.1', 'Vary': 'Accept-Encoding', 'X-Application-Context': 'pine-movie-api', 'Content-Length': '700', 'Connection': 'keep-alive'} is not JSON serializable Traceback (most recent call last): File "/var/lang/lib/python3.6/json/__init__.py", line 238, in dumps **kw).encode(obj) File "/var/lang/lib/python3.6/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/var/lang/lib/python3.6/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "/var/runtime/awslambda/bootstrap.py", line 110, in decimal_serializer raise TypeError(repr(o) + " is not JSON serializable") TypeError: {'Content-Encoding': 'gzip', 'Content-Type': 'application/json;charset=UTF-8', 'Date': 'Thu, 08 Mar 2018 09:21:06 GMT', 'Server': 'Apache-Coyote/1.1', 'Vary': 'Accept-Encoding', 'X-Application-Context': 'recochoku-api', 'Content-Length': '700', 'Connection': 'keep-alive'} is not JSON serializable |
そのため requests.response.header を dict 型に変換する必要がありました。
この記事を書いた人
-
新卒3年目で脱新人を目指してます。
フロントに興味を持ち始めた今日このごろ。
趣味は 麻雀 プログラミング 音楽。
運動不足を感じているため、ダンスを始めようかと思っています。
最近書いた記事
- 2019.06.26コンテナイメージの縮小
- 2019.05.27Chromeのユーザ切り替えで複数のAWS環境の管理をわかりやすくする
- 2019.04.15ECRのライフサイクルポリシー
- 2019.03.29KongでOAuth2の認証手順