|
I tested this locally against current master and this PR branch. On master, exclude_defaults=True is applied correctly for models inside lists, but not for models inside dict values: list: [{'foo': 'foo'}]
dict: {'m': {'foo': 'foo', 'bar': 'bar', 'bla': 'bla'}}
On this PR branch, the dict case matches the list behavior: list: [{'foo': 'foo'}]
dict: {'m': {'foo': 'foo'}}
I also ran: python -m pytest tests/test_jsonable_encoder.py -q
26 passed, 1 skipped
git diff --check master...review-pr-15676 passes, and git merge-tree --write-tree master review-pr-15676 exits successfully, so I don't see whitespace or merge-conflict issues. The change looks correctly scoped because exclude_defaults is a global serialization flag like exclude_unset and exclude_none, which are already forwarded in this dict branch. Update: I also checked the red GitHub checks currently shown on the PR. check-labels is failing because the PR has no required category label yet. The failed Ubuntu coverage job log shows The runner has received a shutdown signal followed by The operation was canceled while setting up uv, before the test suite started, so I don't see evidence of a failing test assertion from this change. |
Sorry, something went wrong.
Summary
jsonable_encoder forwards exclude_defaults to its recursive calls for list/tuple/set items, but omits it when recursing into dict keys and values. So a Pydantic model nested inside a dict keeps its default-valued fields under exclude_defaults=True, while the same model inside a list correctly drops them:
The sibling flags exclude_unset and exclude_none are already forwarded in that same dict branch, so this is a copy/paste inconsistency rather than intended behavior. (include/exclude are intentionally top-level-only and are correctly not forwarded.)
Fix
Forward exclude_defaults in the two recursive jsonable_encoder calls inside the dict branch (for encoded_key and encoded_value), matching how the list/tuple/set branch already does it.
Test plan
Added test_encode_model_with_default_in_container to tests/test_jsonable_encoder.py, asserting a model-in-dict behaves the same as model-in-list under exclude_defaults / exclude_unset.
No behavior change for the already-correct list/tuple/set path; only the dict path is brought into line.
Disclosure: authored with the assistance of an AI tool; fully reviewed and verified by me.