Skip to content

Commit cd92a9b

Browse files
committed
Allow Field.[de|]serialization_getter to be methods (as string argument)
1 parent d1a53b5 commit cd92a9b

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

src/marshmallow/fields.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ class _BaseFieldKwargs(typing.TypedDict, total=False):
103103
error_messages: types.ErrorMessages | None
104104
metadata: typing.Mapping[str, typing.Any] | None
105105
serialization_getter: (
106-
typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
106+
str | typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
107107
)
108108
deserialization_getter: (
109-
typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
109+
str | typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
110110
)
111111

112112

@@ -211,10 +211,10 @@ def __init__(
211211
error_messages: types.ErrorMessages | None = None,
212212
metadata: typing.Mapping[str, typing.Any] | None = None,
213213
serialization_getter: (
214-
typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
214+
str | typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
215215
) = None,
216216
deserialization_getter: (
217-
typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
217+
str | typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None
218218
) = None,
219219
) -> None:
220220
self.dump_default = dump_default
@@ -386,6 +386,14 @@ def _bind_to_schema(self, field_name: str, parent: Schema | Field) -> None:
386386
self.root = self.root or (
387387
self.parent.root if isinstance(self.parent, Field) else self.parent
388388
)
389+
if isinstance(self.serialization_getter, str):
390+
self.serialization_getter = utils.callable_or_raise(
391+
getattr(parent, self.serialization_getter)
392+
)
393+
if isinstance(self.deserialization_getter, str):
394+
self.deserialization_getter = utils.callable_or_raise(
395+
getattr(parent, self.deserialization_getter)
396+
)
389397

390398
def _serialize(self, value: _InternalT | None, **kwargs) -> typing.Any:
391399
"""Serializes ``value`` to a basic Python datatype. Noop by default.

tests/test_fields.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,24 @@ def test_no_serialization_getter_falls_back_to_utils_get_value(self):
151151
field = fields.String()
152152
assert field.get_value({"name": "monty"}, "name") == "monty"
153153

154+
def test_serialization_getter_as_function(self):
155+
def get_upper(obj, attr, default):
156+
return obj[attr].upper()
157+
158+
class MySchema(Schema):
159+
name = fields.String(serialization_getter=get_upper)
160+
161+
assert MySchema().dump({"name": "monty"}) == {"name": "MONTY"}
162+
163+
def test_serialization_getter_as_schema_method(self):
164+
class MySchema(Schema):
165+
def get_upper(self, obj, attr, default):
166+
return obj[attr].upper()
167+
168+
name = fields.String(serialization_getter="get_upper")
169+
170+
assert MySchema().dump({"name": "monty"}) == {"name": "MONTY"}
171+
154172
def test_deserialization_getter_overrides_default_access(self):
155173
class MySchema(Schema):
156174
name = fields.String(
@@ -199,6 +217,24 @@ class MySchema(Schema):
199217
result = MySchema().load({"name": "monty"})
200218
assert result == {"name": "monty"}
201219

220+
def test_deserialization_getter_as_function(self):
221+
def get_upper(data, key, default):
222+
return data[key].upper()
223+
224+
class MySchema(Schema):
225+
name = fields.String(deserialization_getter=get_upper)
226+
227+
assert MySchema().load({"name": "monty"}) == {"name": "MONTY"}
228+
229+
def test_deserialization_getter_as_schema_method(self):
230+
class MySchema(Schema):
231+
def get_upper(self, data, key, default):
232+
return data[key].upper()
233+
234+
name = fields.String(deserialization_getter="get_upper")
235+
236+
assert MySchema().load({"name": "monty"}) == {"name": "MONTY"}
237+
202238

203239
class TestParentAndName:
204240
class MySchema(Schema):

0 commit comments

Comments
 (0)