marshmallow-code / marshmallow-code/marshmallow
Custom Field Logic Bypass
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 7.2k
- Forks
- 738
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 7
Description
If you want to create a field that transforms `None` to a preset value, a custom field is required.
Currently the documentation for "Creating A Field Class" states:
> To create a custom field class, create a subclass of [marshmallow.fields.Field](https://marshmallow.readthedocs.io/en/latest/marshmallow.fields.html#marshmallow.fields.Field) and implement its [_serialize](https://marshmallow.readthedocs.io/en/latest/marshmallow.fields.html#marshmallow.fields.Field._serialize) and/or [_deserialize](https://marshmallow.readthedocs.io/en/latest/marshmallow.fields.html#marshmallow.fields.Field._deserialize) methods.
https://marshmallow.readthedocs.io/en/latest/custom_fields.html#creating-a-field-class
```py
class Integer(fields.Integer):
def _deserialize(self, value, *args, **kwargs):
value = value or 0
return super()._deserialize(value, *args, **kwargs)
class Test(Schema):
foo = Integer(allow_none=True)
Test().load({'foo': None}) # but it produces {"foo": None} instead of {"foo": 0}
```
When `None` (or `missing`) is encountered `_deserialize()` is never executed, because `Field.deserialize()` returns immediately. The current work around appears to require an understanding of undocumented parts of the `Field` implementation and extending `deserialize()` instead. The documentation should probably explain the `_/de/serialize()` and None/missing interaction.
```py
class Amount(fields.Integer):
def deserialize(self, value, *args, **kwargs):
value = value or 0
return super(Amount, self).deserialize(value, *args, **kwargs)
```
A similar use case is having a `Nested` field supply the default values for the nested schema's fields when the parent field is `None`/missing. We may want to explore improving the default behavior in a future version, but for now providing a pattern for this in the docs would be helpful.
```py
class Options(fields.Nested):
def deserialize(self, value, *args, **kwargs):
value = value or {}
return super(Options, self).deserialize(value, *args, **kwargs)
```
Related to #388
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the “Creating A Field Class” section in custom_fields.html and review the documented Field._serialize, Field._deserialize, and deserialize behavior shown in the issue. Clarify how None and missing values bypass _deserialize, and document the deserialize override pattern for custom fields such as Integer and Nested; done means the examples and interaction are clear to readers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100