[python] fix null handling in generated models#24357
Open
fa0311 wants to merge 4 commits into
Open
Conversation
to_dict() rebuilt containers of models with truthiness checks, so None entries were dropped from lists (changing their length) and from dict values. Keep them as explicit nulls instead, and guard the list-of-list / list-of-dict from_dict comprehensions so a null inner container no longer crashes. from_dict() also used 'obj.get(k) is not None' when applying property defaults, which silently replaced an explicit JSON null with the schema default on nullable properties. Check key presence instead (nullable properties only, non-nullable keep the old behavior). get_discriminator_value() now uses obj.get() so a payload without the discriminator property raises the descriptive ValueError instead of a bare KeyError.
The previous commit added an else-branch that assigned None to the per-key accumulators (e.g. _field_dict_of_array[k] = None). mypy fixes the dict value type from the first non-None assignment, so the None branch tripped 'Incompatible types in assignment' on the legacy-model-dictionaries sample. Fold each container branch into a single conditional expression so the accumulator is inferred as Optional from the start. Same output, same null-preserving behaviour.
fa0311
force-pushed
the
fix/python-null-value-serialization
branch
from
July 20, 2026 07:25
569ec4a to
4040d87
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a few ways the
pythongenerator mishandlesnullwhen (de)serializing models.to_dict() drops null entries from containers
to_dict()rebuilds containers of models by hand and skipped falsy entries, soNoneitems disappeared:A dropped element shifts every following index for the consumer, and a dropped map key is just lost. Now the
Noneis kept as an explicitnull. The list-of-list / list-of-dictfrom_dictcomprehensions also crashed on anullinner 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_dictusedobj.get(k) if obj.get(k) is not None else <default>, so an explicit JSONnullwas indistinguishable from an absent key and got replaced by the default:This round-trips as silent data corruption (
from_json(x.to_json())turns an intentionalNoneback 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 bareKeyError, while the code a few lines below builds a descriptiveValueErrorfor unmapped values. The rest of the deserialization stack catchesValueError, so theKeyErrorleaked out. Switched toobj.get().Verified list/map null preservation, nullable-default round-trips, and the discriminator path against generated clients; petstore sample tests still pass.
PR checklist
./mvnw clean packageand regenerated the python samples.master./cc @cbornet @tomplus @krjakbrjak
Summary by cubic
Fix incorrect null handling in generated
pythonmodels to preserve data shape during (de)serialization and align error behavior with the rest of the stack. Keeps explicitNonevalues and avoids crashes withnullinner containers.Noneentries in lists and dict values into_dict(); use single conditional expressions for container items to keep mypy happy.from_dict()checks key presence so an explicitnullisn’t replaced by the default; non-nullable behavior unchanged.from_dict()list-of-list and list-of-dict comprehensions sonullinner containers don’t crash.obj.get()in discriminator lookup so a missing discriminator raises a descriptiveValueErrorinstead of aKeyError.Written for commit 4040d87. Summary will update on new commits.