Skip to content

Move required exploded array query parameters into the exploded form expansion - #8101

Merged
Vincent Biret (baywet) merged 3 commits into
microsoft:mainfrom
Om-singhaI:fix/required-exploded-array-query-parameters
Aug 28, 2026
Merged

Move required exploded array query parameters into the exploded form expansion#8101
Vincent Biret (baywet) merged 3 commits into
microsoft:mainfrom
Om-singhaI:fix/required-exploded-array-query-parameters

Conversation

@Om-singhaI

@Om-singhaI om singhal (Om-singhaI) commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

GetUrlTemplate emits every required query parameter outside the RFC 6570 expression as a literal name={name} pair and never reads Explode. For an array typed parameter with explode: true that template comma joins the values (?ids=1,2,3) when the spec asks for a repeated key (?ids=1&ids=2&ids=3). Since Microsoft.OpenApi defaults style to form for query parameters and Explode to true for form style, every unannotated required array query parameter hits this, and an explicit explode: true in the document is ignored too.

Vincent Biret (@baywet) already prescribed the fix on #4487 in 2024:

Hence I suggested we made a small change to the template building logic to NOT use the required syntax when something is exploded.

That issue went stale before a PR materialized. This picks it up, with one refinement: only array typed parameters leave the required bucket. For a scalar, name={name} and {?name} expand to the same name=value pair, so exploding a scalar changes nothing and moving scalars would only give up the required semantics introduced by #3989 for no serialization gain. The existing tests asserting ?apikey={apikey}&filter={filter} for required strings (which have Explode == true by default) keep passing untouched, and a new test pins the required syntax for a scalar with an explicit explode: true.

Changes

  • OpenApiUrlTreeNodeExtensions.GetUrlTemplate: required query parameters that are array typed and exploded now land in the {?...}/{&...} expression with the * modifier, alongside the optional parameters. The rest of the template composition is untouched.
  • Tests: required exploded array alone (both explicit and defaulted explode), required scalar with explicit explode: true keeping the required syntax, optional exploded array unchanged, and a mix of required scalar, required exploded array, and optional parameter composing to ?apikey={apikey}{&filter*,select*}.
  • CHANGELOG.md entry.

Behavior tradeoff

A required exploded array the caller leaves unset now vanishes from the query string entirely, where the old template emitted a bare ids= pair. RFC 6570 offers no syntax that is both outside an expression and exploded, so the template cannot express required and exploded at the same time; correct serialization of provided values wins over the empty placeholder for missing ones. The changelog entry calls this out.

Full suite is green, dotnet format --verify-no-changes is clean on the touched files.

Fixes #8031
Closes #4487
Related: https://github.com/microsoft/kiota-dotnet/issues/934

…xpansion

Required query parameters were always emitted outside the RFC 6570 expression as literal name={name} pairs, ignoring the explode modifier. An array typed query parameter with explode set to true, the OpenAPI default for query parameters, therefore comma joined its values instead of repeating the key. Array typed exploded parameters now move into the form expansion with the star modifier while scalars keep the required syntax, since scalar expansion is identical either way.

Fixes microsoft#8031

@baywet Vincent Biret (baywet) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the contribution!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes URL template generation in Kiota so required query parameters that are arrays and effectively explode: true are no longer emitted in the “required literal” form (name={name}), which cannot represent exploded arrays per RFC 6570. Instead, those parameters are moved into the RFC 6570 form-style query expansion ({?name*} / {&name*}), restoring repeated-key serialization for arrays (e.g., ids=1&ids=2&ids=3) while preserving the existing “required literal” semantics for scalar required parameters.

Changes:

  • Update OpenApiUrlTreeNodeExtensions.GetUrlTemplate to treat required exploded array query parameters as part of the {?...} / {&...} expression with the * modifier.
  • Add/extend unit tests to cover required exploded arrays (explicit/default explode), required scalars with explode: true, optional exploded arrays, and mixed required/optional composition ordering.
  • Add a CHANGELOG.md entry documenting the behavior change and the RFC 6570 tradeoff when a required exploded array is unset.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs Moves required exploded array query params into {?...} / {&...} expansions via NeedsExplodedExpansion, preserving correct exploded serialization.
tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs Adds regression coverage for required exploded arrays and mixed required/optional scenarios, ensuring scalars keep required literal syntax.
CHANGELOG.md Documents the fix and the intentional tradeoff for unset required exploded arrays per RFC 6570 constraints.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@baywet

Copy link
Copy Markdown
Member

om singhal (@Om-singhaI) can you solve the conflicts on the changelog please?

@baywet Vincent Biret (baywet) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for making the changes!

@baywet
Vincent Biret (baywet) added this pull request to the merge queue Aug 27, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 27, 2026
@baywet
Vincent Biret (baywet) added this pull request to the merge queue Aug 27, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 27, 2026
@Om-singhaI

Copy link
Copy Markdown
Contributor Author

The queue failures are not coming from this branch. The typescript idempotency job against the github description passed on the PR run and then failed in both queue attempts, and the only input that changed in between is the description itself, which the job downloads fresh from github/rest-api-description main. I can reproduce it locally on unmodified main at d5f667d: generating typescript from the current api.github.com.json crashes with error generating the client: Function deserializeIntoWithPath not found in namespace ApiSdk.models, and my branch fails byte for byte the same way. So the description update trips an existing typescript generation bug rather than anything in this change. Happy to open a separate issue with the repro if useful.

@baywet
Vincent Biret (baywet) added this pull request to the merge queue Aug 27, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 27, 2026
@baywet
Vincent Biret (baywet) added this pull request to the merge queue Aug 27, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 27, 2026
@baywet
Vincent Biret (baywet) added this pull request to the merge queue Aug 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 28, 2026
@baywet
Vincent Biret (baywet) added this pull request to the merge queue Aug 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 28, 2026
@baywet
Vincent Biret (baywet) added this pull request to the merge queue Aug 28, 2026
Merged via the queue into microsoft:main with commit 73ab448 Aug 28, 2026
311 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants