I am trying to build a marshmallow scheme to both load and dump data. And I get everything OK except one field.
(If you understand the problem, you don't have to read this).
For load data its type is Decimal
. And I used it like this before. Now I want to use this schema for dumping and for that my flask API responses with: TypeError: Object of type Decimal is not JSON serializable
. OK, I understand. I changed the type to Float
. Then my legacy code started to get an exception while trying to save that field to database (it takes Decimal
only). I don't want to change the legacy code so I looked for any solution at the marshmallow docs and found load_only
and dump_only
params. It seems like those are what I wanted, but here is my problem - I want to set them to the same field. So I just wondered if I can define both fields and tried this:
class PaymentSchema(Schema):
money = fields.Decimal(load_only=True)
money = fields.Float(dump_only=True)
I have been expected for a miracle, of course. Actually I was thinking that it will skip first definition (correctly, re-define it). What I got is an absence of the field at all.
So I tried another solution. I created another schema for dump and inherit it from the former schema:
class PaymentSchema(Schema):
money = fields.Decimal(load_only=True)
class PaymentDumpSchema(PaymentSchema):
money = fields.Float(dump_only=True)
It works. But I wonder if there's some another, native, "marshmallow-way" solution for this. I have been looking through the docs but I can't find anything.
data_key
argument to the field definitionDocumentation mentions, data_key
parameter can be used along with dump_only
or load_only
to be able to have same field with different functionality. attribute
parameter's value will refer the field with its original field name.
So you can write your schema as...
class PaymentSchema(Schema):
decimal_money = fields.Decimal(data_key="money", load_only=True, attribute="money")
money = fields.Float(dump_only=True)
This should solve your problem. I am using data_key
for similar problem in marshmallow with SQLAlchemyAutoSchema
and this fixed my issue.
Note: The key in ValidationError.messages
(error messages) will be decimal_money
by default. You may tweak the handle_error
method of Schema class to replace decimal_money
with money
but it is not recommended as you yourself may not be able to differentiate between the error messages fields.
Thanks.