Repository navigation
docs(downgrader): note validators that reject 1.0 for an integer under 3.0 rules - #362
Conversation
3.1 has no default for a missing or unmapped discriminating value, so tools following the kept discriminator (Hey API types and Zod) pin the default schema's tag to its name and reject values 3.2 routes to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VVaw7PbWyR4kZ18CjgHzqs
… none of 3.1 lets a Discriminator Object carry specification extensions, 3.0 does not, so an `x-` key there made the 3.0 output invalid. Microsoft.OpenApi's 3.0 reader reports it as an error, for example on the `x-discriminator-default` that SwaggerHub's NPP and APDS specs write. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VVaw7PbWyR4kZ18CjgHzqs
…to claude/project-thread-ttohne
…to claude/project-thread-ttohne
…m tag with a default required Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VVaw7PbWyR4kZ18CjgHzqs
…he tag default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VVaw7PbWyR4kZ18CjgHzqs
…to claude/project-thread-ttohne
…lue enum tag Hey API pins each discriminator branch to its tag when the tag is a one-value enum, as a const becomes, so its runtime plugins reject a value that leaves out a tag with a default (Pydantic's Literal default). From 3.1's const it uses the branch as written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VVaw7PbWyR4kZ18CjgHzqs
…to claude/project-thread-ttohne
…r 3.0 rules Python's openapi-schema-validator and jsonschema-rs with draft 4 rules reject a number with a zero fraction for type integer, as 3.0.3 defined an integer; 3.0.4, which the output names, accepts it as 3.1 does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VVaw7PbWyR4kZ18CjgHzqs
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This PR adds one bullet to the tool notes under the #### Limitations list of the 3.1 → 3.0 schema section in packages/downgrader/README.md.
- Draft 4 integer-fraction note — documents that Python's
openapi-schema-validator(OAS30Validator, which openapi-core uses) andjsonschema-rsunder draft 4 rules reject a zero-fraction number such as1.0fortype: "integer", matching how 3.0.3 defined an integer, while 3.0.4 (the version the output names) and 3.1 count it as one, as do both tools' 3.1 rules.
I independently checked the load-bearing facts: OAS 3.0.3 §4.4 ("a JSON number without a fraction or exponent part") and 3.0.4 §4.4 ("both 1 and 1.0 are equivalent, and are both considered to be integers"); jsonschema 4.10.3 (Draft4Validator rejects 1.0, Draft202012Validator accepts); jsonschema-rs's draft-4 is_integer (uses is_written_as_integer, with tests asserting 1.0/1e0/1e2 are not integers under draft 4); and out.openapi = '3.0.4' in v3.1-to-v3.0.ts. The note is accurate and reads consistently with the neighboring tool bullets.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Requested by dinwwwh · project thread
What
This PR adds one bullet to the downgrader README's tool notes, after the kin-openapi bullet.
Some validators reject a number with a zero fraction, such as
1.0, fortype: "integer"when they read a 3.0 document:OAS30Validator), which openapi-core usesThat follows how 3.0.3 defined an integer: "a JSON number without a fraction or exponent part". 3.0.4, the version the output names, counts
1.0as an integer ("both1and1.0are equivalent"). 3.1 does too, and so do the 3.1 rules of both tools.Checked
OAS30Validator({type: integer})rejects1.0and1e0, whileOAS31Validatoraccepts both.Draft4Validatorrejects1.0andDraft202012Validatoraccepts it.1.0from1, so they aren't affected.type: "integer", which code generators need, so the downgrader can't loosen this without turning integers into numbers. That's why this is a docs note only.The other downgrader thread found this through keyword fuzzing.
Generated by Claude Code