Search code examples
pythonmarshmallow

Marshmallow Str() does not work but Function() does


I am trying out marshmallow for serializing my data objects, because even though just writing out json dicts is really damn easy, for some reason everyone thinks it's more pythonic to use a package.

Problem is, it doesn't work the way it's advertised. The Str() field is supposed to make a string from an attribute of the same name; the Function() field is required to perform code execution. I don't think code execution should be required here, but Str() is not working but Function() is.

>>> q.origin
'local.qdb'

>>> from marshmallow import Schema, fields
>>> class StrSchema(Schema):
        origin = fields.Str()

>>> StrSchema().dump(q)
MarshalResult(data={'origin': ''}, errors={})

>>> class FunctionSchema(Schema):
        origin = fields.Function(lambda x: x.origin)

>>> FunctionSchema().dump(q)
MarshalResult(data={'origin': 'local.qdb'}, errors={})

Am I missing something? q here is a complicated object, but it has an _origin attribute and an origin property that just returns the attribute. When I just create a dummy object that has those characteristics, it does not demonstrate the problem. There is no trickery in the origin property of q so I don't know what's wrong. But I'd appreciate any hints.


Solution

  • I found the answer: it is in the utils file, in the function _get_value_for_key:

    def _get_value_for_key(key, obj, default):
        try:
            return obj[key]
        except (KeyError, AttributeError, IndexError, TypeError):
            try:
                attr = getattr(obj, key)
                return attr() if callable(attr) else attr
            except AttributeError:
                return default
        return default
    

    Basically, Marshmallow tries to __getitem__ before it tries getattr; my object was returning empty on __getitem__ rather than raising a key error.

    This is probably a documentation error.