Description
Description
ObjectSerializer::buildQuery
flattens array params (e.g. exclude[]
) and instead of
exclude[]=a&exclude[]=b
it outputs exclude=a&exclude=b
resulting in HTTP contract errors:
[422] Client error: `GET test.com/?exclude=a&exclude=b` resulted in a `422 Unprocessable Entity` response:
{"error":"invalid request query exclude: expected an array, but got `\"exclude\"` instead."}
OpenAPI declaration file content or url
This is the OpenAPI relevant schema:
paths:
/internal/url:
get:
x-stability-level: stable
parameters:
- name: exclude
in: query
required: false
style: deepObject // <---- this affect ObjectSerializer::toQueryValue output
explode: true // <----- this also affect ObjectSerializer::toQueryValue output
schema:
type: array
items:
type: string
Results in generated PHP code from DefaultApi.php:
ObjectSerializer::toQueryValue(
$exclude,
'exclude', // param base name
'array', // openApiType
'deepObject', // style
true, // explode
false // required
)
exclude = [
'exclude[0]' => 'a',
'exclude[1]' => 'b'
]
This appears to confuse `\GuzzleHttp\Psr7\Query::build($data, $encoding_type); in 7.3.0 and it's the same in 7.7.0
such that the output is
exclude=a&exclude=b
causing the HTTP contract to fail.
openapi-generator version
- regression on 7.3.0
- also happening on 7.7.0
Suggest a fix
If you change exclude
field declaration from array
to object
then the output
ObjectSerializer::toQueryValue(
$exclude,
'exclude', // param base name
'object', // openApiType <---------- changed from 'array'
'deepObject', // style
true, // explode
false // required
)
then the output is a single layer array
[
'exclude[0]' => 'a',
'exclude[1]' => 'b'
]
Unfortunately this cannot be added to the OpenAPI schema because it doesn't make sense, the param is actually an array
not an object
.
Then I think the solution is to change a line of code inside ObjectSerializer::toQueryValue
7.3.0
if ($openApiType === 'object' && ($style === 'deepObject' || $explode)) {
return $value;
}
this should also take into account $openApiType === 'array'