swagger-api / swagger-api/swagger-codegen
[JAVA] Retrofit2 client doesn't support path parameters that are collections
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
When declaring a path parameter that is an array with a collectionFormat of csv, the Retrofit2 code generator declares the parameter as a List rather than a CSVParams. When Retrofit generates the URL for the API call, the parameter is incorrectly serialized as [foo,%20bar], which is the result of calling toString on the list.
This is admittedly a very much of an edge case but we're trying to retrofit an OpenAPI specification over an API that has existed for years and which makes use of this. We could probably work around this issue by tweaking the endpoint of the API on the server side but this is something I would rather avoid having to do. If the OpenApi specification allows for such parameters to be declared, code generators should support them.
Swagger-codegen version
2.2.3
Swagger declaration file content or url
This is the declaration of the endpoint — some parts omitted for brevity
"/activities/{id}/streams/{stream_types}": {
"get": {
"operationId": "getActivityStreams",
"parameters": [
{
"name": "id",
"in": "path",
"type": "integer"
},
{
"name": "stream_types",
"in": "path",
"type": "array",
"items": {
"type": "string",
"enum": [
"time",
"distance",
"latlng"
]
},
"collectionFormat": "csv",
"minItems": 1
}
]
}
}
Command line used for generation
swagger-codegen generate -i myspec.json -c config.json -l java -o java
The relevant parts of the config are:
{
"useRxJava2": true,
"library": "retrofit2"
}
Steps to reproduce
- Declare an endpoint with a parameter that is an array with a collectionFormat
- Configure the java generator to use the retrofit2 templates
- Run the generator against the spec and the configuration
This is the generated code
@GET("activities/{id}/streams/{stream_types}")
Observable<StreamSet> getActivityStreams(
@retrofit2.http.Path("id") Integer id, @retrofit2.http.Path("stream_types") List<String> streamTypes
);
Related issues/PRs
None found
Suggest a fix/enhancement
For query parameters, the template to generate query parameters (modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/queryParams.mustache) special-cases collections:
{{#isQueryParam}}@retrofit2.http.Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}}
But the same is not true for path parameters — the template (modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/pathParams.mustache) is much simpler:
{{#isPathParam}}@retrofit2.http.Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/pathParams.mustache and compare it with queryParams.mustache, which already special-cases collection formats. Reproduce the Java Retrofit2 generation using the supplied OpenAPI declaration and configuration. Done means a CSV path collection is generated with the appropriate CSVParams type and is serialized correctly instead of using List.toString().
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100