marshmallow-code / marshmallow-code/marshmallow

Custom Field Logic Bypass

Open
#2,012 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

docs
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.