🐍 Python
object_hook でデコード時にカスタムオブジェクトへ変換する
json.loads()は既定でJSONのオブジェクト({})をPythonのdictに変換しますが、object_hook引数に変換関数を渡すと、辞書が出来上がるたびにその関数を通してから使えます。独自クラスのインスタンスに変換したい場合に使います。
json.loads(s, object_hook=変換関数)
# 変換関数は、デコード中に作られた各dictを受け取り、
# 好きなオブジェクト(そのままdictでもよい)を返す
import json
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point(x=%r, y=%r)" % (self.x, self.y)
def as_point(d):
if "x" in d and "y" in d:
return Point(d["x"], d["y"])
return d
s = '{"x": 1, "y": 2}'
p = json.loads(s, object_hook=as_point)
print(p)
# Point(x=1, y=2)
print(type(p))
#
# 条件に一致しない辞書はそのままdictとして返る
import json
def as_point(d):
if "x" in d and "y" in d:
return "(Pointへの変換はここでは省略)"
return d
s2 = '{"name": "no coords"}'
p2 = json.loads(s2, object_hook=as_point)
print(p2)
# {'name': 'no coords'}
print(type(p2))
#
object_hookが呼ばれるタイミング
- 各
{}ごとに呼ばれる - 入れ子になったJSONの場合、内側の
{}から先に変換関数が適用され、その結果を使って外側が組み立てられる - デフォルトは呼ばれない
object_hookを指定しなければ、通常通り全ての{}がdictのまま返る
💡 AIコードレビュー観点:dumps()側のdefault引数と対になる機能
object_hookはdefault引数のちょうど逆の役割です。defaultでカスタムオブジェクトをJSONに変換して保存し、object_hookで読み込み時に元のクラスへ復元する、という対で設計すると、独自クラスをそのままJSON経由でやり取りできます。AIが生成したコードでdefaultだけ実装されていてobject_hookが無い場合、読み込み側は常に素のdictを受け取ることになり、元のクラスの機能(メソッド等)が使えないことに注意しましょう。