Help us understand the problem. What is going on with this article?

pythonでjson出力する際に対応していない型(e.g. datetime)の値を変換しながら出力したい

pythonでjson出力する際に対応していない型(e.g. datetime)の値を変換しながら出力したい。

対応していない型を含んだ辞書でTypeErrorが発生

pythonでdictをjsonに変換しようとする際にはjson.dumps(json.dump)が使える。
この時、対応していない型の値が含まれていた場合には以下の様な例外が発生する。

# TypeError: datetime.datetime(2000, 1, 1, 0, 0) is not JSON serializable

例えば、datetime objectを含んだ辞書personをjson.dumps仕様とした際には以下のような結果になってしまう。

import json
from datetime import datetime

person = {
    "name": "Foo",
    "age": 20,
    "created_at": datetime(2000, 1, 1)
}

json.dumps(person)
# TypeError: datetime.datetime(2000, 1, 1, 0, 0) is not JSON serializable

default引数に関数を与えることで、対応していない型に対するコールバックを設定する事ができる

json.dumpsは幾つかの引数を取れる。

json.dumps = dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, inden
t=None, separators=None, encoding='utf-8', default=None, sort_keys=False, **kw)
    Serialize ``obj`` to a JSON formatted ``str``.
...

この内のdefault引数に以下のような関数を与えてあげると、対応していない方に対するマッピングを後付で指定することができる。

def support_datetime_default(o):
    if isinstance(o, datetime):
        return o.isoformat()
    raise TypeError(repr(o) + " is not JSON serializable")

今度はjson.dumpsで変換することができる。

person = {
    "name": "Foo",
    "age": 20,
    "created_at": datetime(2000, 1, 1)
}


json.dumps(person, default=support_datetime_default)
# {"created_at": "2000-01-01T00:00:00", "age": 20, "name": "Foo"}

あるいはJSONEncoderを継承したクラスを作成する

json.dumpsにcls引数で変換に利用するクラスを変更できる(defaultではjson.JSONEncoderが使われる)
したがって、以下の様なJSONEncoderを継承したクラスを定義してclsに渡してもOK。

class DateTimeSupportJSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime):
            return o.isoformat()
        return super(DateTimeSupportJSONEncoder, self).default(o)

json.dumps(person, cls=DateTimeSupportJSONEncoder)
# {"created_at": "2000-01-01T00:00:00", "age": 20, "name": "Foo"}
podhmo
wacul
人工知能でWebサイトの課題を発見する AIアナリスト https://wacul-ai.com を開発しています
https://wacul.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした