[python] fix null handling in generated models
Fixes a few ways the python generator mishandles null when (de)serializing models.
to_dict() drops null entries from containers
to_dict() rebuilds containers of models by hand and skipped falsy entries, so None items disappeared:
Container(items=[item, None]).to_dict() # -> {'items': [{...}]} length changed!
Container(mapping={'a': None, 'b': item}).to_dict() # -> {'mapping': {'b': {...}}} key 'a' gone
A dropped element shifts every following index for the consumer, and a dropped map key is just lost. Now the None is kept as an explicit null. The list-of-list / list-of-dict from_dict comprehensions also crashed on a null inner container ('NoneType' object has no attribute ...); those are guarded too.
from_dict() resurrects the default over an explicit null
For a nullable property with a default, from_dict used obj.get(k) if obj.get(k) is not None else <default>, so an explicit JSON null was indistinguishable from an absent key and got replaced by the default:
# property: {type: string, nullable: true, default: "hello"}
Container.from_dict({"note": None}).note # -> "hello" (should be None)
This round-trips as silent data corruption (from_json(x.to_json()) turns an intentional None back into the default). Changed to check key presence for nullable properties; non-nullable properties keep the old behavior.
get_discriminator_value() raises KeyError instead of ValueError
When the discriminator property is missing from the payload, obj[cls.__discriminator_property_name] raised a bare KeyError, while the code a few lines below builds a descriptive ValueError for unmapped values. The rest of the deserialization stack catches ValueError, so the KeyError leaked out. Switched to obj.get().
Verified list/map null preservation, nullable-default round-trips, and the discriminator path against generated clients; petstore sample tests still pass.
PR checklist
- Read the contribution guidelines.
- Ran
./mvnw clean packageand regenerated the python samples. - Filed the PR against
master.
/cc @cbornet @tomplus @krjakbrjak
Summary by cubic
Fix incorrect null handling in generated python models to preserve data shape during (de)serialization and align error behavior with the rest of the stack. Keeps explicit None values and avoids crashes with null inner containers.
- Bug Fixes
- Preserve
Noneentries in lists and dict values into_dict(); use single conditional expressions for container items to keep mypy happy. - For nullable properties with defaults,
from_dict()checks key presence so an explicitnullisn’t replaced by the default; non-nullable behavior unchanged. - Guard
from_dict()list-of-list and list-of-dict comprehensions sonullinner containers don’t crash. - Use
obj.get()in discriminator lookup so a missing discriminator raises a descriptiveValueErrorinstead of aKeyError.
- Preserve