Bind OpenAPI 3.1 multi-type union parameters into any destinations - #154
Merged
Merged
Conversation
mromaszewicz
force-pushed
the
feat/issue-153
branch
from
August 16, 2026 05:11
f2aa995 to
01e3503
Compare
A parameter declared with a 3.1 multi-type union (type: [string, integer]) generates an `any` destination, which the binder rejected unconditionally: "can not bind to destination of type: interface". The binder is destination-driven, and an interface destination carries no information. Add a Types field to BindStyledParameterOptions, BindQueryParameterOptions and BindStringToObjectOptions carrying the union's member list. It is only consulted when the destination is an empty interface, so concrete destinations keep the reflection-driven path unchanged. The value binds to the first member that parses, in specificity order (boolean, integer, number, string) rather than declaration order: JSON Schema defines the type array as an unordered set, and the always-succeeding string member would otherwise shadow the rest. Numeric detection follows the JSON number production (RFC 8259), so "007" and "+1" stay strings instead of being reinterpreted. The bound value's dynamic type is one of exactly bool, int64, float64, string, or []byte. Format "byte" is the one load-bearing format (it changes the wire decoding, base64-decoding the string member); width formats (int32/int64, float/double) and annotation-only formats (date-time, uuid, ...) are ignored by default so that a spec edit to `format` can never silently change the dynamic type a running handler's type switch sees. Applications that want width narrowing opt in via the NarrowUnionNumericFormats package variable — the DefaultQueryEncoder pattern — which makes format int32 produce int32 and format float produce float32, with out-of-range values falling through to the next member. The "null" nullability marker is ignored wherever it appears, whether or not the generator stripped it. Arrays of unions and deepObject-style binding are documented as out of scope. Closes oapi-codegen#153 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mromaszewicz
force-pushed
the
feat/issue-153
branch
from
August 16, 2026 05:22
01e3503 to
567fbb3
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.
A parameter declared with a 3.1 multi-type union (type: [string, integer]) generates an
anydestination, which the binder rejected unconditionally: "can not bind to destination of type: interface". The binder is destination-driven, and an interface destination carries no information.Add a Types field to BindStyledParameterOptions, BindQueryParameterOptions and BindStringToObjectOptions carrying the union's member list. It is only consulted when the destination is an empty interface, so concrete destinations keep the reflection-driven path unchanged. The value binds to the first member that parses, in specificity order (boolean, integer, number, string) rather than declaration order: JSON Schema defines the type array as an unordered set, and the always-succeeding string member would otherwise shadow the rest. Numeric detection follows JSON number grammar, so "007" and "+1" stay strings instead of being reinterpreted, and the bound value matches what the same token would produce inside a JSON document. Format applies only to its host member and only where it changes decoding: int32/int64 and float/double select numeric widths, byte base64-decodes the string member; annotation-only formats are ignored per 3.1 semantics. Non-scalar members and the "null" marker are skipped.
Closes #153