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