[dart] fix: explode object query parameters - #24868
Open
wiebren wants to merge 1 commit into
Open
Conversation
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 dart client handed
the whole map to _queryParams, which stringified it with Map.toString() into a
single parameter (filter={tld: com, createdDate:gte: 2023-01-01}).
The generated api now iterates an exploded map entry by entry at the call
site; _queryParams is left alone, since it never receives style or explode
and is still the right fallback for every other parameter. A free-form
object is typed Object in dart and needs a cast to Map; a declared map does
not. 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.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ
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 query parameter whose schema is an object and whose
style/explodeare left at theirdefaults —
style: form,explode: true— must go on the wire as one parameter per entry,keyed by the property name alone. The
dartclient stringified the whole map withMap.toString()into a single parameter instead, whilecsharp,javaandphpgot itright.
Given:
called with
{"tld": "com", "createdDate:gte": "2023-01-01"}:tld=com&createdDate%3Agte=2023-01-01filter=%7Btld%3A+com%2C+createdDate%3Agte%3A+2023-01-01%7D— dart'sMap.toString(), percent encodedThe cause
dart2/api.mustache— every query parameter was handed whole to_queryParams, whichreceives only a collection format (empty for a map) and falls through to
parameterToString(value), i.e.value.toString(). No style or explode reaches theruntime.
The fix mirrors the accepted python change in #24802: the generated api iterates an exploded
map entry by entry at the call site —
— and
_queryParamsis left alone, since it is shared by every call site and is still theright fallback for a parameter that is not an exploded map. A free-form object is typed
Objectin dart and needs the cast; a declared map does not get one, so the analyzer staysclean (
dart analyzeon the generated fixture client: no issues).deepObjectandexplode: falseparameters keep the exact line they produced before.Verified on the wire, not just asserted
The client was generated from the new fixture and pointed at a server that echoes its own raw
request target back:
filter(object, defaults)filter=%7Btld%3A+com%2C+createdDate%3Agte%3A+2023-01-01%7Dtld=com&createdDate%3Agte=2023-01-01typedFilter(map, defaults)Map.toString()shapetld=com&createdDate%3Agte=2023-01-01deepFilter(style: deepObject)deepFilter=%7Btld%3A+com%2C…%7DflatFilter(explode: false)flatFilter=%7Btld%3A+com%2C…%7DKnown gaps, called out deliberately
Declared object models. A
$refed object model as a query parameter isisModel, notisMap, so it still goes on the wire whole. Pre-existing, and the same gap the sibling PRsdocument — iterating a model would put the dart property names on the wire rather than the
wire names. Left for a follow-up.
deepObjectandexplode: falsekeep their previous single-Map.toString()parameter.Both are wrong per the spec (
deepFilter[tld]=comandflatFilter=tld,com,…respectively),both were wrong before this change, and both go on the wire byte for byte as they did
before — same scoping as the sibling PRs.
A non-map value in a free-form object parameter now throws a
TypeErrorat the castinstead of going on the wire as its
toString(). This matches python, where a non-dictraises at
.items().Tests
modules/openapi-generator/src/test/resources/3_0/exploded-object-query-param.yamlcoversthe four combinations that decide the wire format:
DartClientCodegenTest#testExplodedObjectQueryParameterIt fails without the fix (verified by stashing only the template change). All 13 tests in
DartClientCodegenTestpass.PR checklist
./bin/generate-samples.shforbin/configs/dart-*.yaml;./bin/utils/export_docs_generators.shproduced no diff).1 sample file changed:
petstore_client_lib_fake/lib/api/fake_api.dart, from thepetstore fixture's
languageparameter — a declared map with the default style, thesame parameter that changed in the python sibling. The dart-dio samples are untouched,
since that generator has its own templates.
Generated with Claude Code
Summary by cubic
Fixes the Dart client so object query parameters with the default
style: formandexplode: truego on the wire as one parameter per entry, keyed by property name, instead of as a singleMap.toString()-stringified parameter.Behavior
deepObjectandexplode: falseparameters keep their previous wire format, byte for byte.TypeErrorat the cast instead of being stringified.Known gaps
$refed object models as query parameters are still sent whole; pre-existing behavior left for a follow-up.deepObjectandexplode: falseoutput remains spec-incorrect but unchanged from before.Written for commit bbcc510. Summary will update on new commits.