Fix minItems for all-optional array-like Structs by binggao1230 · Pull Request #1124 · msgspec/msgspec · GitHub
Skip to content

Fix minItems for all-optional array-like Structs - #1124

Open
binggao1230 wants to merge 1 commit into
msgspec:mainfrom
binggao1230:fix-json-schema-array-like-defaults
Open

Fix minItems for all-optional array-like Structs#1124
binggao1230 wants to merge 1 commit into
msgspec:mainfrom
binggao1230:fix-json-schema-array-like-defaults

Conversation

@binggao1230

Copy link
Copy Markdown
Contributor

Problem

For an array_like=True Struct where every user field has a default, msgspec.json.schema reports minItems one too high. An untagged Struct gets minItems: 1 even though msgspec.json.decode accepts [] and fills all defaults; a tagged Struct similarly gets 2 even though a tag-only array is valid. Generated schemas therefore reject payloads accepted by msgspec itself.

The trailing-default loop stored the zero-based enumerate index and later used it as a count. When the loop never encountered a required field, that count was one short.

Fix

Count trailing optional fields explicitly before calculating minItems. The existing required-field and empty-Struct boundaries remain unchanged.

The regression test covers both tagged and untagged Structs and includes a default_factory, while checking the generated schema against the public decoder contract.

Testing

  • just test tests/unit/test_schema.py — 124 passed, 2 skipped
  • just test — 6412 passed, 113 skipped
  • just check — lint, format, and spelling checks passed

@codspeed-hq

codspeed-hq Bot commented Jul 16, 2026

Copy link
Copy Markdown

@fallenmi fallenmi left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified exact head 58ae07bcad83e518d749b7580a69cf91f7b3f4de.

  • Exact base a1ebbcdcf65b794370956e41c8c925cc366ed6f0 failed 8/50 matrix cases: every tagged or untagged array-like Struct with zero required and 1–4 defaulted fields advertised minItems one too high, while the decoder accepted the minimal payload.
  • The head and a clean current-main integration pass all 50 combinations (0–4 required × 0–4 defaulted × tag on/off), with schema minItems matching the decoder minimum.
  • Exact-head full unit suite: 6,052 passed / 473 skipped. Current-main integration: 6,052 passed / 473 skipped. Ruff check/format and git diff --check are clean; all live upstream checks are green.

The counter correction also preserves the mixed required/default and zero-field boundaries. Approving this unchanged head.

Reviewed with OpenAI Codex assistance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants