swagger-api / swagger-api/swagger-codegen

[Java] [resttemplate client] Array Path Parameters are not serialized according to Spec

Open
#12,192 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

I have an OAS 3 spec with an operation that declares a path parameter of type array(string).
I have used the maven codegen plugin to generate a Java Client with the resttemplate library.

When invoking the service using the generated client, a failure may occur.
The root cause is that client does not control the serialization of the path argument:

// generated from resttemplate/api.mustache
public ResponseEntity<Void> myOperationWithHttpInfo(List<String> args) throws RestClientException {
   ...
   Map<String, Object> uriVariables = new HashMap();
      uriVariables.put("args", args);
      String path = UriComponentsBuilder.fromPath("/some/{args}/path").buildAndExpand(uriVariables).toUriString();

The UriComponentsBuilder#fromPath#buildAndExpand eventually just calls toString() on the List object, sending a URL
that depends on the implementation of List rather than the API specification.
For example, given List.of("a", "b", "c"), the client constructs a path "/some/[a,b,c]/path" instead of the expected "/some/a,b,c/path" (note the extra square brackets)

Swagger-codegen version

Swagger-codegen 2.4.31, with swagger-codegen-maven-plugin 3.0.42, on top of spring-web 5.3.19

Swagger declaration file content or url
openapi: 3.0.1
info:
  title: My API
  version: 0.0.0

paths:
  /some/{args}/path:
    get:
      operationId: myOperation
      parameters:
        - in: path
          name: args
          required: true
          schema:
            type: array
            items:
              type: string
      responses:
        200:
          description: "Internal error"
          content: { }
Command line used for generation

Swagger-codegen Maven Plugin version 3.0.42
Language: Java
Librar: resttemplate

Steps to reproduce

Generate the client as above
invoke client.myOperation(List.of("a","b","c"));
The operation may fail - possibly silently - depending on the implementation of toString() for the chosen List class

Related issues/PRs

Loosely related to issue #11987

Suggest a fix/enhancement

As a workaround, clients should make sure to use a List class that implements toString() as needed
For example, for a simple style, not exploded path argument:

class PathListAdapter<T> extends ArrayList<T> {
    // constructors and other overrides as needed
   public PathListAdapter(List<T> inner) {
      super(inner);
    }

    @Override
    public String toString() {
      return this.stream()
          .map(Objects::toString)
          .collect(Collectors.joining(","));
    }
}

This approach could be moved into the mustache template:

// generated from resttemplate/api.mustache
public ResponseEntity<Void> myOperationWithHttpInfo(List<String> args) throws RestClientException {
   ...
   Map<String, Object> uriVariables = new HashMap();
      uriVariables.put("args", new PathListAdapter<>(args));   // <---- wrap
      String path = UriComponentsBuilder.fromPath("/some/{args}/path").buildAndExpand(uriVariables).toUriString();

The choice of adapter (toString) should then be driven by the 'style' and 'expand' parameter attributes, for conformance with the spec.

I have looked briefly into subclassing the UriComponentsBuilder internal components, or trying to pass a formatter, but I have not been able to find an immediate, clean way that is not tightly coupled to the UriComponentsBuilder implementation.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with resttemplate/api.mustache and reproduce the generated client from the OpenAPI declaration in the issue, focusing on how the array path argument reaches UriComponentsBuilder. Done means generated clients serialize array path parameters according to their style and expand attributes rather than relying on the List implementation's toString().

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.