0
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

【Python】Object of type is not JSON serializable

Last updated at Posted at 2024-07-12

オブジェクトをjsonに変換しようとするとタイプエラーが発生したので記録
TypeError: Object of type SampleClass is not JSON serializable

原因

JSONへのエンコーダとしてはデフォルトでjson.JSONEncoderを使用しており、変換の際の対応は以下になります。

Python JSON
dict object
list,tuple array
int,float number
True true
False false
None null

つまり、ここにない型をエンコーディングしようとするとTypeErrorが出るというわけです
object, Enum, datetime型などをjsonにしようとした際に遭遇する問題でしょうか

import json
from datetime import date
from enum import Enum
class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

class SampleClass:
    def __init__(self, name):
        self.name = name

# datetime
json.dumps(date.today()) # TypeError: Object of type date is not JSON serializable

# Enum
json.dumps(Color.RED) # TypeError: Object of type Color is not JSON serializable

# object
json.dumps(SampleClass("bob")) # TypeError: Object of type SampleClass is not JSON serializable

対応

JSONEncoderクラスを拡張してデフォルト以外の型にも対応できるようにします。
サブクラスを用意し、default()メソッドをオーバーライドし、任意のオブジェクトを上記対応表の認識可能な型に変換します。

具体的には以下のようにJSONEndecoderのサブクラスでdefault()を実装し、デフォルト以外の型の場合にどのような変換を行うかを定義します。

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        # Enum -> str,int
        if isinstance(obj, Enum):
            return obj.value # or obj.name
        # datetime -> str
        if isinstance(obj, datetime):
            return obj.isoformat() # https://docs.python.org/ja/3.7/library/datetime.html#datetime.datetime.isoformat
        # object -> dict
        elif isinstance(obj, object) and hasattr(obj, '__dict__'):
            return obj.__dict__
        # dict,str,int,... -> default       
        return super().default(obj)

これを使って先ほどの例を試します

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

class SampleClass:
    def __init__(self, name: str, color: Color, created_at: datetime):
        self.name = name
        self.color = color
        self.created_at = created_at


sample = SampleClass("bob", Color.RED, datetime.now())
sample_json = json.dumps(sample, cls=CustomJSONEncoder)
print(sample_json) # {"name": "bob", "color": 1, "created_at": "2024-07-12T14:34:53.927615"}

無事にシリアライズできるようになりました。
ref : https://docs.python.org/ja/3/library/json.html#module-json

0
0
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
0
0