元派遣プログラマの自称技術系ブログです。雑記とか自作のオープンソースプロジェクトの話とか。
Javaとか組込とかできます。お仕事ください。

JSON形式でPickleがしたい!

Pythonオブジェクトのシリアライズにはpickleモジュールがあるが、こいつは独自形式のバイナリを出力する。

どこかの超人のようにバイナリをそのまま読めないので、JSON形式でpickleできるようなモジュールを作った。

pickle utility to json format . · GitHub


こんな感じのコードを書くと

if __name__ == "__main__":
    """
    テスト
    """
    class A(JsonPicklable):
        def __init__(self):
            self.a=1
            self.b="a"
    class B(JsonPicklable):
        def __init__(self):
            self.a=2
            self.b="b"
            self.c=A()
    b=[A(),B()]

    print("----")
    #ダンプ
    ds=dumps(b)
    print("dump:"+ds)
    #ロード
    lo=loads(ds)
    print("load:"+str(lo))
    #ダンプ
    ds2=dumps(lo)
    print("dump:"+ds2)

こんな感じで相互変換できる。

dump:[{"__cls": "A", "d": {"a": 1, "b": "a"}}, {"__cls": "B", "d": {"a": 2, "b": "b", "c": {"__cls": "A", "d": {"a": 1, "b": "a"}}}}]
load:[<__main__.A object at 0x00007fed81747b08>, <__main__.B object at 0x00007fed81747b40>]
dump:[{"__cls": "A", "d": {"a": 1, "b": "a"}}, {"__cls": "B", "d": {"a": 2, "b": "b", "c": {"__cls": "A", "d": {"a": 1, "b": "a"}}}}]


相互変換可能なのはpicklableなオブジェクトのみ。それ以外はエラーになるので注意。
メンバ変数がpicklableクラスとディクショナリだけならば、対象クラスにJsonPicklableを多重継承しておけばOK。

クラスをpicklableにする方法はこの辺を参考にしてね。

pickle --- Python オブジェクトの直列化 — Python 3.8.2 ドキュメント
Pickleの動作をカスタマイズするためのメソッドをテストする - Qiita


基本的には__setstate__と__getstate__を書き加えればよいはずです。__new__と__getnewargs__は使わないでください。
PyPIにはまだ登録してないのでしばらくはコピペでご利用ください。