Skip to content

[BUG] PHP Client - ObjectSerializer::buildQuery flattens array params resulting invalid URL params (param=a&param=b vs param[]=a&param[]=b) #19233

Closed
@serbanghita

Description

@serbanghita
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
        )

Screenshot 2024-07-24 at 13 20 09

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

Screenshot 2024-07-24 at 14 10 43

[
 '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'

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions