soy-curd's blog

へぼプログラマーです [https://twitter.com/soycurd1]

python用のシリアライザmarshmallowで辞書オブジェクトとJSONの相互変換

pythonのシリアライザであるmashmallowを業務で使うことになったのでメモ。

はじめに

webアプリケーションを作成していると、

{
    'hoge':'1',
    'foo':'2',
    'bar':3
}

のような辞書オブジェクトを、

'{"foo": "2", "hoge": "1", "bar": 3}'

のようなJSONに変換したい場合(やその逆)がある。その時に使えるのが、marshmallowである。

github.com

インストール

pip install marshmallow

でOK。

簡単な例

まず、marshmallowを使うには、スキーマというものを定義する必要がある。

たとえば上の例だったら、以下のように定義する。

# スキーマを定義
class HogeSchema(Schema):
    hoge = fields.Str(required=True)
    foo = fields.Str(required=True)
    bar = fields.Int(required=True)

これを使うと、

hoge_data = {
    'hoge':"1",
    'foo':'2',
    'bar':3,
}

data, err = HogeSchema().dumps(hoge_data)
pprint(data)
pprint(err)

# '{"foo": "2", "hoge": "1", "bar": 3}'
# {}

というふうにJSONに変換することができる。

逆の場合は、

hoge_data = '{"hoge":"1","foo":"2","bar":3}'

data, err = HogeSchema().loads(hoge_data)
pprint(data)
pprint(err)

# {'bar': 3, 'foo': '2', 'hoge': '1'}
# {}

として、loadsを用いるとJSONストリングを辞書オブジェクトに変換できる。

なお、marshmallowはバリデーション機能も持っているので、さきほどのスキーマを用いて、

hoge_data = '{"hoge":"1","foo":"2"}'

のようなフィールドの不足したデータをデシリアライズしようとすると、

# {'bar': ['Missing data for required field.']}

と、エラー理由を戻り値に格納してくれる。

応用

marshmallowであるが、フィールドを拡張することで、各フィールドの値を好きなように変換することもできる。例えば、

class IppaiHogeHoge(fields.Field):
    def _serialize(self, value, attr, obj):
        if value == "1":
            return value * 10
        else:
            return value

class HogeSchema(Schema):
    hoge = IppaiHogeHoge(required=True)
    foo = fields.Str(required=True)
    bar = fields.Int(required=True)

のように定義すると、dumpした結果は、

data, err = HogeSchema().dumps(hoge_data)
pprint(data)
pprint(err)
# '{"foo": "2", "hoge": "1111111111", "bar": 3}'
# {}

のようにできるので便利。

おわりに

上の方法とは別に、JSON -> class変換はmarshmallowでできるようなのだが、 class -> JSON変換の方法がまだわからないので、もう少し調べる。。。

Pythonプロフェッショナルプログラミング 第2版

Pythonプロフェッショナルプログラミング 第2版