Skip to content

keep_none option to skip Field._serialize() on None values #1096

@PhilMarsh

Description

@PhilMarsh

I have optional attrs in some of my app-level objects.
My app-level objects are fully explicit: missing optional fields are explicitly set to None instead of being left unset.
I want my Schema to be similarly explicit on dump (ie: never skip fields), while being permissive on load (ie: allow missing fields as None).

So the behavior I want for my Fields is:
A) on load, missing or None is deserialized to None.
B) on dump, None is serialized to None.

Requirement A is easily satisfied by missing=None.
Requirement B requires more work. For custom types, I must add an is None check to the override of Field._serialize().

This asymmetry of load and dump behavior is strange to me for a couple reasons:

  1. Load-time optionality is controlled dynamically via Field parameters, which are stated in the Schema.
    But dump-time optionality is controlled statically by the Field implementation, forcing all Schemas to accept the same behavior (or use some sort of Field factory to customize behavior). I think it is common to have types which are optional in some Schemas and required in other Schemas.
  2. None may be a valid attr value on the parent object/Schema, but None is not a valid value for my custom Field's data type. For example, given:
    Foo.bar = Bar()
    
    Assuming .bar is optional, Foo.bar = None is a valid assignment. But None is not a valid Bar object. So a BarField should not be responsible for serializing a None. I would actually expect BarField to raise some TypeError-like if it was given a None to serialize.

My proposal is to add a keep_none parameter to Field to make this dump behavior configurable.
Behavior is:

  • During serialization, if an attr is found to be None and keep_none is True, then return None as the serialized value and do not call Field._serialize().

This seems similar to #229, except I don't want to skip the None Fields; I want to keep them as None in the serialized output.

EDIT 1: Requirement A is satisfied by missing=None (which implies allow_none=True), not by allow_none=True alone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions