Skip to content

[pull] master from OpenAPITools:master - #816

Merged
pull[bot] merged 13 commits into
transparencies:masterfrom
OpenAPITools:master
Sep 28, 2026
Merged

pull[bot] merged 13 commits into
transparencies:masterfrom
OpenAPITools:master

Conversation

@pull

@pull pull Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

wiebren and others added 13 commits September 28, 2026 14:39
* fix: [go] explode object query parameters

A query parameter whose schema is an object and whose style/explode are left at
their defaults — style: form, explode: true — must go on the wire as one
parameter per entry, keyed by the property name alone. The go client bracketed
it as filter[category]=books instead.

parameterAddToHeaderOrQuery in go/client.mustache bracketed every map whatever
style it was handed. The reflect.Slice case immediately above it already
branches on style == "deepObject", so the map case looks like an oversight. The
generated api passes the style correctly; nothing downstream read it.

The flattening applies to the top level only. The recursive call no longer
carries the style down, so anything nested inside an entry keeps the path it has
accumulated: {profile: {name: "x"}} is profile[name]=x, and two siblings holding
the same property name stay distinct — {a: {x: 1}, b: {x: 2}} is a[x]=1&b[x]=2
rather than a pair of colliding x= entries. Nested slices are unaffected, since
the slice branch only special cases deepObject and so behaves identically for an
empty style and for form.

* fix: [go] an array element does not inherit the form flattening

A form style query parameter whose value is an array of maps reached the
map branch one level down with the style still set, so the entries were
keyed by their property names alone and the accumulated parent path was
dropped. Reset the style when descending into array elements, mirroring
the reset the map branch already does for its entries: only a map that is
the parameter's direct value is exploded to bare property names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Go3AyndcGwv5tFTwo9aBfy

* test: [go] cover the array of objects the element reset exists for

The fixture declared four object parameters and no array, so the
assertions added for the element reset in 470b7e0 only matched template
text that every generated client.go carries: they held whatever the
fixture contained.

Add the array of objects, and deliberately not exploded. That is the
only shape that reaches the array branch of parameterAddToHeaderOrQuery:
with explode: true the api template unrolls the slice itself and hands
each element over as a map, which enters the map branch instead, so an
exploded array would have left the branch as uncovered as no array at
all. Not exploded, the whole slice arrives as one form style value:

    parameterAddToHeaderOrQuery(localVarQueryParams, "arrayFilter", r.arrayFilter, "form", "csv")

which is asserted, and is derived from the spec rather than from the
template.

The behaviour itself lives in generated go rather than in the generator,
so it is not reachable from a codegen test. Exercising the helper in a
generated client directly, with a []map[string]interface{} under style
form: filter[a]=1 with the reset, a=1 without it, while a map that is
the parameter's own value stays a=1 either way.

mvn -pl modules/openapi-generator -Dtest=GoClientCodegenTest test:
28 tests, 0 failures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01894FEkx3sDA5wTqjeEo33D

* chore: [go] drop the stray go.mod and go.sum changes

Running the go toolchain in the issue_20079_go_regex_wrongly_translated
sample rewrote its go.mod and go.sum, and the rewrite was swept into the
array element commit. bin/generate-samples.sh emits neither, so the
samples up to date job reverted both files and failed on the dirty tree.
Restore them to what the generator produces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHEXQ9zWNyGwVnWPJJnzSo

* fix: [go] skip nil entries of an exploded object query parameter

A nil entry of a form style exploded map went on the wire as the literal
"null" (nullValue=null), and so did a nil element of a list an entry
holds (anyList=x&anyList=null&anyList=2). Both are now left out, after
unwrapping interfaces and pointers, matching the kotlin port.

A typed nil pointer, such as (*string)(nil), panicked with
"reflect.Value.Interface on zero Value" because the pointer branch called
Elem().Interface() without a nil check. It is now left out as well; that
branch is shared with deepObject, where it turns the same panic into an
omitted value. deepObject is otherwise unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: [go] skip nil entries under deepObject too

The previous commit left nil entries out of a form style exploded map but
not out of a deepObject one, so the same map went on the wire two ways: a
nil entry was dropped under form and sent as filter[k]=null under
deepObject. deepObject was also inconsistent with itself, because the nil
check added to the pointer branch already dropped a typed nil pointer
there.

Move the entry check ahead of the form branch, so it applies whatever the
style, and skip a nil element in the array branch as well. The elements
that survive keep the index they had, so filter[l][0] and filter[l][2]
stay where they are rather than closing the gap; the index names a
position in the array the caller passed, and renumbering would quietly
move the remaining values.

Nothing changes for a non-nil value, and a nil parameter passed at the
top level still goes out as key=null.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* revert: [go] keep deepObject's null for a nil entry

This reverts cd901bc. deepObject sending [key]=null for a nil entry is
behaviour the petstore sample pins in TestQueryDeepObject, and it is the same
on master, so it stays out of a change about form style. Form style keeps
skipping nil entries, and the nil check in the pointer case stays.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test: [go] pin the nil-entry skip inside the form branch

The assertion on parameterValueIndirect alone also matched the reverted
layout that skipped nil for every style. Pinning what follows the skip
fails if it is ever moved ahead of the style branch again, which would
break deepObject's [key]=null that TestQueryDeepObject expects.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore: [go] trim the exploded object comments, test and fixture

The shipped comments shrink to one line each, parameterValueIndirect
returns true once it has unwrapped a non-nil value, the codegen test
keeps only the assertions that fail without each fix, and arrayFilter
leaves the shared fixture so it is byte-identical across the ports again.
The fixture's description now names the three combinations it covers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: [go] keep the validity check in parameterValueIndirect

The constant true reported an invalid reflect.Value as usable. No caller
passes one today, but the check guards v.Interface() against a panic and
costs nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: [python] explode object query parameters

A query parameter whose schema is an object and whose style/explode are left at
their defaults — style: form, explode: true — must go on the wire as one
parameter per entry, keyed by the property name alone. The python client
JSON-encoded the whole object into a single parameter instead.

python/api.mustache appended the object whole, and it was JSON encoded by
ApiClient.parameters_to_url_query, which sees no style or explode. Exploded maps
are now appended entry by entry. parameters_to_url_query's dict branch is left
alone: it is shared by every call site and is still the right fallback for a
parameter that is not exploded.

python/api_client.mustache quoted values and never quoted names. That was
harmless while every name came from baseName in the document, but an exploded
object takes its names from the object, so the names became runtime data for the
first time and a name carrying & or = would break the URL. Names are now quoted
too.

* fix: [python] do not apply a collection format to an exploded object entry

An exploded object query parameter takes its names from the object, so a
property name can collide with the name of a sibling array parameter that
declares a collection format. parameters_to_url_query looked the name up in
collection_formats without checking that the value was a collection, so the
scalar was iterated character by character.

In the petstore fixture, testQueryParameterCollectionFormat declares
context: multi alongside the exploded map language. Calling it with
language={"context": "en"} produced context=e&context=n, and a csv sibling
turned https://x.test into h,t,t,p,s,%3A,/,/,x,.,t,e,s,t.

The collection format now applies only when the value really is a list or a
tuple. Every genuine array parameter is unaffected — multi, csv, ssv and pipes
all serialize byte for byte as before.

Reported by cubic on #24802.

* test: [python] exercise the exploded-name collision guard at runtime

Two runtime tests on parameters_to_url_query in the hand-maintained
petstore sample tests: a scalar entry named like a declared array
parameter goes out as itself, and the declared array parameter still gets
its collection format.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Go3AyndcGwv5tFTwo9aBfy

* fix: [python] explode object query parameters with declared properties

An object with declared properties becomes a model rather than a dict, so it
was flagged isModel, missed the isMap branch and was still json encoded as a
single parameter. With form style and explode a model is now serialized with
sanitize_for_serialization first, so its entries carry the names the
properties have on the wire and unset properties are left out, and then
exploded like a map. A oneOf or anyOf model holding a primitive does not
serialize to a dict and stays a single parameter; deepObject and explode:
false are unchanged.

An exploded entry holding a list now repeats its name per item
(photoUrls=a&photoUrls=b), as java, go and typescript-axios do, instead of
going out as the str() of the list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: [python] skip null entries and explode a oneOf holding a list

A null map value went on the wire as k=None and a null list item as l=None,
because parameters_to_url_query quotes str(None). Both exploded branches now
skip a null value and a null item, as kotlin, dart and go do.

The model branch also appends the serialized value rather than the model. For a
oneOf or anyOf holding a primitive that changes nothing on the wire, since
param_serialize runs sanitize_for_serialization over every query parameter
before parameters_to_url_query, but one holding a list now repeats the parameter
name per item instead of sending the list's repr.

Adds a runtime test for the quoting of exploded property names, which only the
generated text covered until now, and one for a model whose optional properties
are left unset.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor: [python] explode query objects in one ApiClient helper

The map and model branches repeated the same loop in every generated
operation. ApiClient.explode_query_object now serializes the value and
returns one pair per entry, so each branch is a single call, and the
helper gets direct unit tests. Comments shrink to one line, the shared
fixture's description names the three combinations it covers, and the
test titles say what they check.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore: [python] regenerate the python-httpx2 samples

They landed on master after this branch was cut, so they did not carry
the exploded query object changes yet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…n all-optional models (#24877)

* fix: [csharp] conditionalSerialization must not flag value-typed properties the caller never set

With conditionalSerialization=true, an all-optional model's public constructor
took every value-typed property as a plain value type and then guarded the
serialization flag with `if (this.AutoRenew != null)` — always true for a
non-nullable bool/int/enum, so every value-typed property was marked as set the
moment the model was constructed. A partial-update command built as
`new UpdateThingCommand(note: "renamed")` went on the wire as
{"autoRenew":false,"note":"renamed"}: an invented false on the exact
operation where it does the most damage. (The C# compiler flags the old guard
itself: CS0472 'the result of the expression is always true'.)

Optional value-typed constructor parameters without a default value are now
nullable, and the flag is only raised when the argument was actually provided:

    if (autoRenew != null)
    {
        this._AutoRenew = autoRenew.Value;
        this._flagAutoRenew = true;
    }

Required properties, properties with a spec default, reference types, and the
public property surface (plain value-typed properties with flag-raising
setters) are all generated byte-for-byte as before; only the optional
value-type constructor path changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ

* test: [csharp] cover optional enums and nullable value types in the conditionalSerialization constructor

Extends the conditional-serialization-value-types fixture with an optional
inline enum, a nullable enum and a nullable integer. The test now asserts
that enums take the guarded `.Value` path, that `nullable: true` value types
keep their existing null check, and that no parameter type is emitted as `T??`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test: [csharp] drop conditionalSerialization assertions the remaining ones already imply

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: [kotlin] explode object query parameters in the jvm-okhttp client

A query parameter whose schema is an object and whose style/explode are left at
their defaults — style: form, explode: true — must go on the wire as one
parameter per entry, keyed by the property name alone. The jvm-okhttp client
serialized the whole map with toString() into a single parameter instead
(filter={tld=com, ...}), and a declared map came out as concatenated
Pair.toString()s. The jvm-ktor library already explodes these correctly.

The query building in api.mustache now iterates an exploded map entry by
entry, the same way jvm-ktor does. deepObject and explode: false objects
keep their previous wire format, byte for byte.

The new test fixture covers the four style/explode combinations that decide
the wire format; the test fails without the template change.

No sample changes: no kotlin sample spec declares a free-form or map-typed
query parameter with the default style, the echo api's object query
parameters are all model-typed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ

* fix: [kotlin] skip nulls, repeat collections and append exploded query entries

Follow-up to the review of the exploded object query parameters in the
jvm-okhttp client:

- a null map entry is left out instead of going on the wire as the
  literal "null" (Any?.toString() returns "null" rather than throwing)
- a collection value repeats the key once per element instead of being
  sent as the collection's toString(); scalar values and elements go
  through parameterToString, so dates get the same format as other query
  parameters
- an exploded entry named like another query parameter no longer
  overwrites it, or gets overwritten by it: the exploded parameters are
  now emitted after every declared query parameter and append to an
  existing entry, so both values end up on the wire

To place the exploded parameters after the declared ones, the codegen
flags them with x-kotlin-explode-form-object (jvm-okhttp libraries only)
and api.mustache emits them in a second pass; the three duplicated
required/optional/nullable branches of the first version are gone.
deepObject and explode: false parameters are unchanged, and no sample
changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore: [kotlin] trim the exploded query comment and simplify the entry loop

One comment line above the loop instead of three; the when now only picks
the elements and filterNotNull/parameterToString run once. Drop the
defensive !isModel check, which no other port has: a map-typed parameter
is never isModel. Fix the fixture description, which claimed four
style/explode combinations where it covers three, and retitle the test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test: [kotlin] keep the shared fixture byte-identical with the other ports

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
… but never deserializes to it (#24878)

* fix: [php] enumUnknownDefaultCase must reach deserialization, not just declare the member

With enumUnknownDefaultCase=true the generator adds UNKNOWN_DEFAULT_OPEN_API to
every enum class, but ObjectSerializer::deserialize still threw
InvalidArgumentException for any wire value outside the list — the error
message even advertises 'unknown_default_open_api' as an allowed value while
refusing to produce it. The flag changed nothing observable: one new enum
value from the server still destroyed the whole response.

ObjectSerializer::deserialize now returns the enum's declared unknown-default
member for an unrecognized value, guarded twice: the branch is only generated
when enumUnknownDefaultCase=true (clients generated without the flag are
byte-identical to before), and at runtime it only fires for enum classes that
actually declare UNKNOWN_DEFAULT_OPEN_API. Java's fromValue behavior under the
same flag is the reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ

* test: [php] one assertion per enumUnknownDefaultCase serializer case

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test: [php] keep the assertion on the UNKNOWN_DEFAULT_OPEN_API defined() guard

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…r but never deserializes to it (#24879)

* fix: [ruby] enumUnknownDefaultCase must reach build_from_hash, not just declare the member

With enumUnknownDefaultCase=true the generator adds UNKNOWN_DEFAULT_OPEN_API to
every enum class's constants and all_vars, but the enum's build_from_hash still
raised 'Invalid ENUM value' for any wire value outside the list — the flag
changed nothing observable, and one new enum value from the server still
destroyed the whole response.

build_from_hash now falls back to the enum's own unknown-default member — the
last declared enum var, which under the flag is always the appended
UNKNOWN_DEFAULT_OPEN_API. The tolerance lives in each generated enum class;
without the flag the generated code is byte-identical to before and still
raises. Java's fromValue behavior under the same flag is the reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ

* test: [ruby] drop enumUnknownDefaultCase assertions the build_from_hash checks imply

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test: [ruby] keep the enumUnknownDefaultCase member value assertions

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: William Cheng <wing328hk@gmail.com>
…nullable enum fields (#24894)

* [kotlin] fix: make the enumUnknownDefaultCase moshi fallback adapters null-safe

SerializerHelper registers a moshi EnumJsonAdapter with withUnknownFallback
per enum, but EnumJsonAdapter is not null-safe and it is registered bare:
any model with a nullable enum property throws "value was null! Wrap in
.nullSafe() to write nullable values" on a null value, reading and writing
alike. The flag traded unknown-value tolerance for a regression on every
optional enum field. Append .nullSafe() in both branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz

* test: [kotlin] shorten the null-safe adapter test comment

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…25028)

Kotlin wraps a property name that is not a valid identifier in back-ticks,
for example `2ndField` for a schema property named "2nd_field". The model
templates rendered that name with a double-brace Mustache tag, which HTML
escapes it, so the generated KDoc read:

    @PARAM &#x60;2ndField&#x60; An optional property ...

Switch the two affected templates to a triple-brace tag, matching what
kotlin-client, kotlin-server, ktor2 and jaxrs-spec already do.

No committed sample changes, because no existing kotlin-spring or
kotlin-vertx sample has a property name that needs back-ticks. The new
test uses param-json-property.yaml, which does.


Claude-Session: https://claude.ai/code/session_01VBn7VWUxZL6mTUbg21xNjm

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…pile (#24899)

* [rust] fix: exploded deepObject free-form query parameters do not compile

The exploded deepObject branch walks every map-flagged parameter with
.len()/.iter() - fine for a HashMap-typed map (an object schema with
declared additionalProperties), but a bare free-form object is a
serde_json::Value, which has neither, so the generated crate did not
compile. Split the branch on isContainer and walk the Value through
as_object(): a non-object Value sends nothing, matching the parameter's
declared object shape. The second of the two follow-ups promised in
#24866's body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz

* [rust] rework: route exploded deepObject maps through parse_deep_object

Review pointed out the branch emitted unprefixed json-quoted pairs - not
the deepObject wire format the style asks for - and that was true of the
pre-existing HashMap iteration too. Both shapes (typed map and free-form
serde_json::Value) now take crate::apis::parse_deep_object, the route the
non-explode branch already uses: name[key]=value on the wire, one code
path, and the Value shape compiles because to_value accepts both. The
fixture gains a required-nullable parameter so all patched sites are
exercised, and the test registers the generated tree for cleanup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz

* [rust] tidy: drop narrating template comments, pin the typed-map wire shape

The four comment copies repeated what the identical non-explode block
already says. The test is renamed for what it checks, and the fixture's
`filter` becomes a typed map (`additionalProperties: {type: string}`),
the shape whose wire format this change affects.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…#23953)

A model with a discriminator is rendered as an interface. Because the
generator knows every subtype at generation time, that interface can be
sealed, which lets callers use exhaustive `when` matching and stops
external code from adding implementors that the discriminator mapping
does not know about.

Adds `useSealedDiscriminatorInterfaces` (default true). Set it to false
to restore the plain `interface` rendering, which is needed when the
generated interface is implemented from outside the generated package.

Also declares SchemaSupportFeature.allOf, which the generator supports
but did not advertise.


Claude-Session: https://claude.ai/code/session_01VBn7VWUxZL6mTUbg21xNjm

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… original (#25015)

* [rust] Log a sanitized identifier only when it differs from the cased original

* [rust] Keep the rename warning test to its own log events
…ug output (#25019)

* [rust] Redact credentials in the reqwest Configuration and ApiKey Debug output

* [rust] Redact the token source in Configuration Debug and test every credential
@pull pull Bot locked and limited conversation to collaborators Sep 28, 2026
@pull pull Bot added the ⤵️ pull label Sep 28, 2026
@pull
pull Bot merged commit 4c2d787 into transparencies:master Sep 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants