ちょっと前の話
APIでjsonをPOSTするときありますよね。
私はknowledgeの記事か何かをPythonを使ってAPIから更新しようとしました。
こんな中身(例)
article = { 'title': 'タイトルだよ', 'text': '中身だよ' }
が、詳細は忘れてしまいましたがエラーでPOSTできませんでした。
stackoverflowかなにかで調べたらjson.dumpしろとあったので試したところ上手くいきました。
何が違うの?
私はpythonをよく使いますがpythonの辞書型とjsonって書き方同じですよね。
何をエラーになることがあるんでしょうか。
という訳でちょっと調べました。
検証環境
WSLのubuntu18です。
masashi@DESKTOP-N095TND:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.2 LTS Release: 18.04 Codename: bionic masashi@DESKTOP-N095TND:~$ uname -a Linux DESKTOP-N095TND 4.4.0-17763-Microsoft #864-Microsoft Thu Nov 07 15:22:00 PST 2019 x86_64 x86_64 x86_64 GNU/Linux masashi@DESKTOP-N095TND:~$ python3 --version Python 3.6.9
結果は一発で出た
type関数で一発でした。
- 変数
>>> type(article) <class 'dict'>
- json.dumps
>>> type(json.dumps(article)) <class 'str'>
- 辞書型: そのまま辞書型
- json型: 文字列
だったんですね。
辞書型データをPOSTしようとしてこけたってことですね。
dump, loadで変換する
厳密にはdumpsとloadsです。
dump, loadはファイルを読み込むとき使う?って感じです。
jsonの関数で辞書型と文字列の行き来が出来るみたいです。
特定の値を取りたいときは辞書型にしないと取れませんね。
(findで頑張れば無理くりで取れそうですが)
- dumps: 辞書型 → 文字列
ヘルプ
dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) Serialize ``obj`` to a JSON formatted ``str``.
- loads: 文字列 → 辞書型
ヘルプ
loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) Deserialize ``s`` (a ``str``, ``bytes`` or ``bytearray`` instance containing a JSON document) to a Python object.
dumpsだとエラーになりますが、
json型をloadsすれば辞書型になり値が取れます。
>>> json.dumps(article)['title'] # 辞書 → json Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: string indices must be integers >>> >>> json.loads(json.dumps(article))['title'] # json → 辞書 'タイトルだよ' >>>
なるほどねー
むすび
何となく使っていたjsonですが、整理したことで実態がわかりました。
(検証としては薄っぺらーいですが)
最近APIは可読性の観点でxmlよりjsonが主流になっていると思うので
これからバンバン使っていきたいです。