marshmallow icon indicating copy to clipboard operation
marshmallow copied to clipboard

Bug: Custom Method serialization of List items throws AttributeError

Open benedekh opened this issue 2 years ago • 2 comments

Let's have the following Schema:

class ExampleSchema(Schema):
	dummy_list = fields.List(fields.Method(serialize="serialize_me"))

	def serialize_me(self, obj):
		return [str(value) for value in obj["dummy_list"]]

Let's have the following serialization code:

obj = {"dummy_list": ["hello", "world"]}
dumped = ExampleSchema().dump(obj)

ExampleSchema().dump(obj) throws AttributeError: 'List' object has no attribute 'serialize_me' error.

The full stack trace is:

    dumped = ExampleSchema().dump(obj)
..\src\marshmallow\schema.py:399: in __init__
    self._init_fields()
..\src\marshmallow\schema.py:975: in _init_fields
    self._bind_field(field_name, field_obj)
..\src\marshmallow\schema.py:1034: in _bind_field
    field_obj._bind_to_schema(field_name, self)
..\src\marshmallow\fields.py:757: in _bind_to_schema
    self.inner._bind_to_schema(field_name, self)
..\src\marshmallow\fields.py:1858: in _bind_to_schema
    getattr(schema, self.serialize_method_name)
E   AttributeError: 'List' object has no attribute 'serialize_me'

The bug exists in marshmallow 3.16.0.

benedekh avatar May 29 '22 18:05 benedekh

I still need to get my head around this. I suppose Tuple would be impacted as well.

In your example, I don't understand why you use List in the first place. Shouldn't it be

class ExampleSchema(Schema):
	dummy_list = fields.Method(serialize="serialize_me")

	def serialize_me(self, obj):
		return [str(value) for value in obj["dummy_list"]]

?

lafrech avatar Jun 26 '22 21:06 lafrech

@lafrech: That would be also a way to go. However, I wanted to keep the same data types for the field as in the data class.

Originally, I discovered the bug in a @dataclass, where I declared the fields type-correctly and then defined a Schema separately, because I had some special fields in the @dataclass that could not be (de)serialized normally. One of these fields was List[CustomDataType] (where CustomDataType is the type which had to be (de)serialized manually).

benedekh avatar Jun 28 '22 19:06 benedekh