みなさんこんにちは!
JSONファイルは正しく扱えていますか?PythonでJSONを出力の際、文字化けしてしまったり、datetime型がうまく扱えずにエラーがでてしまったり、エンコード問題に悩まされたりしていませんか?
今日はそんな方たちのために、JSONのdumpsについて詳しく見ていきたいと思います!
json dumpsとは
さて、実際にdumps関数をのどのように使うのか見ていまえに、そもそもdumps関数がどんなものかということについて見ていきます。
dumps関数とはデータをJSON形式にエンコードすることのできる関数です。jsonライブラリでは、loads関数がデコード、dumps関数がエンコードとなっています。
エンコードとはデータを別の型に変換してくれることで、デコードとはエンコードされた型をもとに戻すことです。
loads関数や、そもそもJSONが何か怪しいという方は以下の記事で詳しく説明しているので見てみてください。
json dumpsを使ってみよう!
さて、それでは実際にどのように使うのかみていきましょう。
Pythonでjsonファイルを扱うには標準モジュールであるjsonをインポートする必要があるので以下の一文を忘れないようにしましょう。
import json
実際のコードを見ていきましょう。
import json dict = {"name": "tarou", "age": 23, "gender": "man"} enc = json.dumps(dict) print(dict) print(type(dict)) print("******************") print(enc) print(type(enc))
{'name': 'tarou', 'age': 23, 'gender': 'man'} <class 'dict'> ****************** {"name": "tarou", "age": 23, "gender": "man"} <class 'str'>
このように、ディクショナリ型をエンコードしたことによって文字列に変わったことがわかりますね。上で紹介したloads関数はこの逆で文字列として受け取ったものをディクショナリ型で返してくれます。
つまり、JSONのオブジェクトとして受け取るための関数がloads関数ということですね。
フォーマットを整えてdumpしよう
ここが初学者の間違いポイントなのですが、実際にファイルに書き出したいときはdump関数を使います。
dump関数と、dumps関数を同じものだと思っている方は多いですが、dump関数は、ファイルとして保存するための関数で、dumps関数はエンコード(辞書型を文字列に変換)するための関数であるということです。
しっかりと違いを理解するようにしましょう!
さて、実際の使い方をみていきましょう。
import json dict = {"name": "tarou", "age": 23, "gender": "man"} json_file = open('test.json', 'w') json.dump(dict, json_file)
このように、open関数でファイルを指定して、dump関数で第1引数に中身、第2引数にファイルを指定することで書き出すことができます。
test.json
{"gender": "man", "age": 23, "name": "tarou"}
きちんと、書き込めていますがJSONファイルなのに、改行などがないですね。情報量が多くなれば改行なども適正に入れて見やすくしてほしいですよね。
そんなときは第3引数にインデント幅を指定してやると、フォーマットしてくれます。
import json dict = {"name": "tarou", "age": 23, "gender": "man"} json_file = open('test.json', 'w') json.dump(dict, json_file, indent=2)
test.json
{ "gender": "man", "age": 23, "name": "tarou" }
可読性が向上しましたね。
datetime型をdumpsしてみよう
さて、次はdatetime型を含むディクショナリ型をエンコードしてみましょう。
import json from datetime import datetime dict = {"now": datetime.now()} print(dict) json.dumps(dict)
例えばこのように、ディクショナリの中にdatetime型のオブジェクトが入っていた場合実行すると、
{'now': datetime.datetime(2018, 11, 10, 20, 5, 23, 37646)} Traceback (most recent call last): File "test.py", line 8, in <module> json.dumps(dict) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default o.__class__.__name__) TypeError: Object of type 'datetime' is not JSON serializable
このようにエラーになってしまいます。
JSONにはdatetime型が定義されていないためこのようなことが起こります。こういう場合は第2引数にdefaultを指定してやり、そこでエンコーダを拡張する関数を呼び出す必要があります。
まずは、コードと結果からみていきましょう。
import json from datetime import datetime def expireEncoda(object): if isinstance(object, datetime): return object.isoformat() dict = {"now": datetime.now()} enc = json.dumps(dict, default=expireEncoda) print(enc) print(type(enc))
{"now": "2018-11-10T20:21:24.524550"} <class 'str'>
きちんとdumpsできていますね。
default引数に関数を指定してあげると、対応してないほうのデータを引数として持ち関数を呼び出すことができます。
つまり、ここでは、objectという変数には、datetimeの内容が入っています。
isinstanceとはdatetimeモジュールをインポートしたことで使えるようになった関数で第一引数の型が第二引数であるかどうかをチェックしてくれています。
そして、自作したexpireEncodaはTrueの場合そのオブジェクトを文字列で返してくれるという関数になっていすね。
少し難しいですが、実際にコードを書いてみると理解できますのでよくわからない方は手を動かしてみましょう!
日本語の文字化けに対応しよう
import json dict = {"name": "太郎", "age": 23, "gender": "男"} enc = json.dumps(dict, indent = 2) print(enc)
{ "name": "u592au90ce", "age": 23, "gender": "u7537" }
このようにdumpsでエンコードを行っているとき、日本語が変な文字列に変換されてしまうという方もいるのではないでしょうか?
これはJSONの仕様でUnicodeが出力されているためです。そんなときは、
import json dict = {"name": "太郎", "age": 23, "gender": "男"} enc = json.dumps(dict, indent=2, ensure_ascii=False) print(enc)
このように、第2引数に”ensure_ascii”を”False”を指定してやると、
{ "name": "太郎", "age": 23, "gender": "男" }
思うようにdumpsしてくれました。
まとめ
いかがでしたでしょうか。今日は、JSONのエンコードであるdumpsについて詳しくみていきました。
エンコード、デコードの違い、dumps、dumpの違い、様々な状況でのdumpsなどこの記事の内容を完全に理解できれば、JSONのdumpsはバッチリです!
冒頭で紹介したloadsなども合わせてマスターしてJSONマスターになりましょう!
それでは!!