15
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSONファイルにdatetimeとか保存したいやん?

Posted at

前置き

Pythonの標準ライブラリjson.dumpは、辞書型のオブジェクトの内容をそのまま保存でき、仕事でも重宝しています。
しかし難点があって、扱えるのは

  • 数値型
  • 文字列型
  • リスト型
  • 辞書型

といった基本型のオブジェクトだけであり、datetimeオブジェクトなど時刻の情報をJSONファイルに保存するときは

record_time = datetime.now()
obj = {
    'RecordTime': record_time.strftime('%Y%m%d-%H%M%S')
}
...

のように一度文字列に変換しないといけないし、
JSONファイルからdatetimeオブジェクトを生成するときも 

obj['RecordTime'] = datetime.strptime(obj['RecordTime'], '%Y%m%d-%H%M%S')

っていちいち変換しないといけないし、不便だなぁ。

そう思っていた時期が、僕にもありました。

そんなあなたにJSONEncoder

そんなある日、jsonモジュールのドキュメントを眺めていたら、見つけました。
これを使えば、datetimeなどのオブジェクトと、文字列や数値との変換をjson.dumpを実行する時に同時に実行してくれるそうです。

たとえば、

record = {
    "singleTimestamp": datetime.datetime(2019, 1, 29, 19, 29, 2, 234680),
    "listedTimestamps": [
        datetime.datetime(2019, 1, 29, 19, 57, 2, 234693),
        datetime.datetime(2019, 1, 29, 19, 47, 2, 234695),
        datetime.datetime(2019, 1, 29, 19, 37, 2, 234697)
    ],
    "nested": {
        "timestamp": datetime.datetime(2019, 1, 29, 19, 31, 2, 234689)
    }

こんなデータをJSONに保存したいと思ったら、

from json import JSONEncoder
class DatetimeJSONEncoder(JSONEncoder): # JSONEncoderを継承させる
    
    def default(self, o):
        if type(o).__name__ == 'datetime':     # 値がdatetime型だったら、
            return o.strftime('%Y%m%d-%H%M%S') # 文字列に変換して返す
        else:
            return o

のようにJSONEncoderを継承する形で新しいクラスを定義し、default()メソッドに、エントリーのtypeとその変換の仕方を対応させて書いて、

with open('jsonencodertest.json', 'w') as fp:
    json.dump(record, fp, indent=2, cls=DatetimeJSONEncoder)

と、cls引数にそのクラスを指定してあげれば良いだけです。

最後に

やっぱドキュメント読むって大事ですね。

15
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?