dahlia / iso4217

ISO 4217 currency data package for Python
https://pypi.org/project/iso4217/
60 stars 12 forks source link

Not possible to serialise into JSON #4

Closed daaain closed 5 years ago

daaain commented 5 years ago

Thanks a lot for this package!

I'm trying to use it as a more robust way of working with currencies instead of just currency codes as string, and it's working quite well except for JSON serialisation (for data to be exposed through an API).

I had a look at the code and can't see any __repr__ or __str__ defined, could that be the issue? I'm using simplejson.encoder.JSONEncoder together with Marshmallow schemas, but I'm not 100% sure how these try to do the serialisation / deserialisation.

dahlia commented 5 years ago

Python's standard enum.Enum in itself provides default __str__() and __repr__() implementations. However, its __str__() currently returns a string like 'Currency.usd' and indeed looks like it can be better.

On the other hand, the problem with marshmallow.Schema is probably because it only supports few built-in types like int and datetime.datetime. You should define a custom field for iso4217.Currency:

import iso4217
from marshmallow import fields

class Currency(fields.Field):
    def _serialize(self, value, attr, obj, **kwargs):
        if value is None:
            return None
        return value.code

    def _deserialize(self, value, attr, data, **kwargs):
        return None if value is None else iso4217.Currency(value)
daaain commented 5 years ago

Thank you for the quick and thorough reply, really appreciated!

Your answer put me on the right path and in the end I managed to make it work using marshmallow_enum without having to manually define a custom field.

from marshmallow_enum import EnumField
from iso4217 import Currency

class ChargeSchema(ma.ModelSchema):
    currency = EnumField(Currency, by_value=True)

This works for both serialisation and deserialisation as uppercase currency code which is exactly what I wanted 👌