OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.46k stars 6.49k forks source link

[PHP][BUG] Query params of type array are incorectly serialized as "multi" #1763

Open Yogarine opened 5 years ago

Yogarine commented 5 years ago
Description

Individual query params with type array and no style defined are incorrectly always serialized as "multi", while I believe it should be just comma-seperated.

In io.swagger.v3.parser.util.OpenAPIDeserializer.getParameter() (~line 1411) if a property is "in" query and of type array, it sets the style to form. The property Parameter.explode is then always set to true.

This causes the collectionFormat to always be set to multi.

In api.mustache the serializeCollection() call is hardcoded to allow "multi".

In the resulting url the query string is encoded like components=0%3DProfiles%261%3DCharacters%262%3DCharacterProgressions, but I can't imagine why an array would need to be encoded like that, since an array, according to the OpenAPI spec, should be just a list.

openapi-generator version

3.3.4-SNAPSHOT

OpenAPI declaration file content or url

https://raw.githubusercontent.com/Bungie-net/api/master/openapi.json

A specific path, as example:

{
  "/Destiny2/{membershipType}/Profile/{destinyMembershipId}/": {
    "summary": "Destiny2.GetProfile",
    "description": "Returns Destiny Profile information for the supplied membership.",
    "get": {
      "tags": [
        "Destiny2"
      ],
      "description": "Returns Destiny Profile information for the supplied membership.",
      "operationId": "Destiny2.GetProfile",
      "parameters": [
        {
          "name": "components",
          "in": "query",
          "description": "A comma separated list of components to return (as strings or numeric values). See the DestinyComponentType enum for valid components to request. You must request at least one component to receive results.",
          "schema": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Destiny.DestinyComponentType"
            }
          }
        },
        {
          "name": "destinyMembershipId",
          "in": "path",
          "description": "Destiny membership ID.",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64"
          }
        },
        {
          "name": "membershipType",
          "in": "path",
          "description": "A valid non-BungieNet membership type.",
          "required": true,
          "schema": {
            "$ref": "#/components/schemas/BungieMembershipType"
          }
        }
      ],
      "responses": {
        "200": {
          "$ref": "#/components/responses/Destiny.Responses.DestinyProfileResponse"
        }
      },
      "deprecated": false
    }
  }
}

#/components/responses/Destiny.Responses.DestinyProfileResponse:

{
  "Destiny.DestinyComponentType": {
    "enum": [
      "0",
      "100",
      "101",
      "102",
      "103",
      "104",
      "200",
      "201",
      "202",
      "203",
      "204",
      "205",
      "300",
      "301",
      "302",
      "303",
      "304",
      "305",
      "306",
      "307",
      "308",
      "400",
      "401",
      "402",
      "500",
      "600",
      "700",
      "800",
      "900"
    ],
    "type": "integer",
    "description": "Represents the possible components that can be returned from Destiny \"Get\" calls such as GetProfile, GetCharacter, GetVendor etc...\r\nWhen making one of these requests, you will pass one or more of these components as a comma separated list in the \"?components=\" querystring parameter. For instance, if you want baseline Profile data, Character Data, and character progressions, you would pass \"?components=Profiles,Characters,CharacterProgressions\" You may use either the numerical or string values.",
    "format": "int32"
  }
}
Command line used for generation
generate \
      --generator-name  "php" \
      --config          "openapi-config.php.json" \
      --input-spec      "https://raw.githubusercontent.com/Bungie-net/api/master/openapi.json" \
      --output          "/local/bungie-sdk-php"

openapi-config.php.json:

{
  "packageName": "bungie-sdk-php",
  "composerVendorName": "yogarine",
  "composerProjectName": "bungie-sdk-php",
  "invokerPackage" : "Bungie",
  "modelPackage": "Model",
  "variableNamingConvention": "camelCase",
  "srcBasePath": "src",
  "gitUserId": "Yogarine",
  "gitRepoId": "bungie-sdk-php",
  "validateSpec": false,
  "removeOperationIdPrefix": true
}
Suggest a fix

A quick fix I use to get it to work for me is to just set the $allowCollectionFormatMulti param in the ObjectSerializer::serializeCollection() to false in the response function in api.mustache.

But I think it needs be investigated whether the style should be set to form when a query param is declared as array. I would like to know the reasoning for this.

If this was done like this for the sake of backwards compatability, then perhaps we need to add an option to control this.

@wing328 @jebentier @dkarlovi @mandrean @jfastnacht @ackintosh @ybelenko

spawn-guy commented 5 years ago

according to this the defaults are style:form explode:true the other thing is, as it seems, the explode param is ignored :/ https://github.com/OpenAPITools/openapi-generator/pull/3984#issuecomment-536914876

ybelenko commented 4 years ago

Is this issue fixed by #3984 PR?