0

I have an endpoint that accepts and sends back objects of the form {a: 1, b: 2, c:3} where either b or c is missing. To precise, admissible objects are {a: 1, b: 2}, {a: 1, c:3} where the values are free to choose.

@RestController
@RequestMapping("/v42")
public class MyAPI {

    @PostMapping("/subsets")
    public Subset getSubsets(@RequestParam Subset subset) {

        return subset;
    }

}

Internally the JSON object is parsed into a subclass of Subset:

@JsonDeserialize(using = SubsetDeserializer.class)
public abstract class Subset {
}

@AllArgsConstructor
public class SubsetAB extends Subset {
    int a,b;
}
@AllArgsConstructor
public class SubsetAC extends Subset {
    int a,c;
}

But since the parent class has no fields the generated spec does not list them:

paths:
  /v42/subsets:
    post:
      tags:
      - pet-api
      operationId: getSubset
      parameters:
      - name: subset
        in: query
        required: true
        schema:
          $ref: '#/components/schemas/com.myservice.api.v42.Subset'
      responses:
        200:
          description: OK
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/com.myservice.api.v42.Subset'
...
components:
  schemas:
    com.myservice.api.v42.Subset:
      type: object

How can I annotate my Subset class so that if shows as having either the form SubsetAB or SubsetAC?

I've tried:

Defining my own examples:

@PostMapping("/subsets")
@ApiResponses(value = {
    @ApiResponse(responseCode = "200", description = "Subset that comes back", content = {
        @Content(mediaType = "application/json", examples = {
            @ExampleObject(name = "subsetAB", description = "With A and B", value = "{\"a\": 1, \"b\": 2}"),
            @ExampleObject(name = "subsetAC", description = "With A and C", value = "{\"a\": 1, \"c\": 3}")
        })
    })
})
public Subset getSubset(@io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(examples = {
        @ExampleObject(name = "subsetAB", description = "With A and B", value = "{\"a\": 1, \"b\": 2}"),
        @ExampleObject(name = "subsetAC", description = "With A and C", value = "{\"a\": 1, \"c\": 3}")
})) @RequestBody Subset subset) {

    return subset;
}

This works pretty good already:

paths:
  /v42/subsets:
    post:
      tags:
      - pet-api
      operationId: getSubset
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/com.myservice.api.v42.Subset'
            examples:
              subsetAB:
                description: With A and B
                value:
                  a: 1
                  b: 2
              subsetAC:
                description: With A and C
                value:
                  a: 1
                  c: 3
        required: true
      responses:
        200:
          description: Subset that comes back
          content:
            application/json:
              examples:
                subsetAB:
                  description: With A and B
                  value:
                    a: 1
                    b: 2
                subsetAC:
                  description: With A and C
                  value:
                    a: 1
                    c: 3
...
components:
  schemas:
    com.myservice.api.v42.Subset:
      type: object

I have examples for input and output and can also see them nicely displayed in the /swagger-ui.html endpoint. However, the schema definition is still empty. And it would be convenient to just define and reference the schemas and have the examples generated automatically.

peer
  • 4,171
  • 8
  • 42
  • 73
  • Is there any way to add the resources file content to the `@ExampleObject`? I am trying to add the `@ExampleObject` from the `resources file` using `ref` but its not working for some reason. I have posted my question: https://stackoverflow.com/q/71616547/7584240 – BATMAN_2008 Mar 30 '22 at 20:31

0 Answers0