JSON → Object 変換(構造が単純な場合)

JSON を読込み任意のオブジェクトにする場合、
 オブジェクトが単純な構造=ネストで任意の構造のオブジェクトを持たない!
という比較的単純な構造の場合に限り、
次のサンプルのように、json.load実行object_hook を定義して渡すことで解決する。

JSONから変換されるオブジェクトのクラス

class User():
    @property
    def _name(self):
        return self.name
    @_name.setter
    def _name(self, value):
        self.name = value
    @property
    def _flag(self):
        return self.flag
    @_flag.setter
    def _flag(self, value):
        self.flag = value
    @property
    def _time(self):
        return self.time
    @_time.setter
    def _time(self, value):
        self.time = value

object_hook で実行するメソッドの定義
isinstance() で、dict :辞書の時に、リフレクションである setattr 関数で値をセットして
User を返します。

def parser(obj):
    if isinstance(obj, dict):
        for k,v in obj.items():
            obj[k] = parser(v)
    elif isinstance(obj, list):
        for i,e in enumerate(obj):
            obj[i] = parser(e)
    elif isinstance(obj, str):
        try:
            obj = datetime.strptime(obj, '%Y-%m-%d %H:%M:%S')
        except (ValueError, AttributeError):
            pass
    if isinstance(obj, dict):
        u = User()
        for k,v in obj.items():
            setattr(u, k, v)
        return u
    return obj

対象のJSON

string = '{"name":"Apple","flag":true,"time":"2020-12-09 17:21:03"}'

実行

user = json.loads(string, object_hook=parser)

print(type(user))
print('%s %r %s' % (user.name, user.flag, user.time.strftime('%Y/%m/%d %H:%M:%S')))

結果

<class '__main__.User'>
Apple True 2020/12/09 17:21:03