duplicated mapping key - support for different content types on the same path & method
Opened this issue ยท 8 comments
currently when writing a controller with different methods for the same path but different content-types the resulting openapi.yml is invalid since it will generate two entries of the same method instead of reusing the same method and just adding the second content type.
example:
expected result:
openapi: 3.0.0
info:
title: "openapi-v3-test"
version: "0.0.1-SNAPSHOT"
description: "<h1>openapi-v3-test</h1><p>Test for th use of openapi v3</p>"
license:
name: "Apache License, Version 2.0"
url: "https://www.apache.org/licenses/LICENSE-2.0"
servers: []
paths:
"/hello/world":
get:
description: "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service\nconfiguration data from the AEM config service."
tags:
- "Hello"
summary: "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service\nconfiguration data from the AEM config service."
deprecated: false
operationId: sayHelloV1
parameters:
- name: "Accept-Language"
in: header
description: "Standard HTTP Accept-Language header"
required: false
schema:
type: string
style: simple
responses:
"200":
description: "Success"
content:
"application/json+v1":
schema:
description: "Success"
type: string
"application/json+v2":
schema:
description: "Success"
type: string
components: {}
actual result:
openapi: 3.0.0
info:
title: "openapi-v3-test"
version: "0.0.1-SNAPSHOT"
description: "<h1>openapi-v3-test</h1><p>Test for th use of openapi v3</p>"
license:
name: "Apache License, Version 2.0"
url: "https://www.apache.org/licenses/LICENSE-2.0"
servers: []
paths:
"/hello/world":
get:
description: "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service\nconfiguration data from the AEM config service."
tags:
- "Hello"
summary: "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service\nconfiguration data from the AEM config service."
deprecated: false
operationId: sayHelloV1
parameters:
- name: "Accept-Language"
in: header
description: "Standard HTTP Accept-Language header"
required: false
schema:
type: string
style: simple
responses:
"200":
description: "Success"
content:
"application/json+v1":
schema:
description: "Success"
type: string
"application/json+v2":
schema:
description: "Success"
type: string
get:
description: "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service\nconfiguration data from the AEM config service."
tags:
- "Hello"
summary: "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service\nconfiguration data from the AEM config service."
deprecated: false
operationId: sayHelloV2
parameters:
- name: "Accept-Language"
in: header
description: "Standard HTTP Accept-Language header"
required: false
schema:
type: string
style: simple
responses:
"200":
description: "Success"
content:
"application/json+v2":
schema:
description: "Success"
type: string
components: {}
That should be easy to fix. But I do not have the time to do it myself right now.
If you can fix it yourself, I will be happy to accept the PR.
@Robbilie Could you provide some sample code. Since it is a difference, whether you have "different methods for the same path but different content-types" (as stated in your description) or one method for two different content-types (as also stated in your description).
For the first case, the actual result is absolutely correct, since you have one path and 2 'get' definitions with different 'operationId' representing the different methods.
"absolutely correct" in what sense? Certainly not in the sense of "valid open API yaml" :)
Errors
Hide
Parser error duplicated mapping key
Jump to line 40
OK, I take back my sentence stating that the generated yaml is correct.
But the to be able to help you, could you provide some sample code of your controller.
You seem to have 2 controller methods for the path "/hello/world", one named "sayHelloV1" and one named "sayHelloV2".
Maybe this is helpful, especially the comment from Damon Sutherland.
Also have a look here.
@RestController
public interface VehicleFunctionsController {
@GetMapping(value = {"/vehicles/{vin}/services"}, produces = {"application/vnd.example.functionlist.v3+json",
"application/vnd.example.error.v1+json"})
@Operation(description = "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service configuration data from the AEM config service.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Success", content = @Content(
mediaType = "application/vnd.example.functionlist.v3+json",
schema = @Schema(implementation = VehicleFunctionsListV3.class))),
@ApiResponse(responseCode = "403", description = "user is non paired guest user / anonymous and is not owner", content = @Content(
mediaType = "application/vnd.example.error.v1+json",
schema = @Schema(implementation = ExceptionResponseMessage.class))),
@ApiResponse(responseCode = "500", description = "Internal error during request execution", content = @Content(
mediaType = "application/vnd.example.error.v1+json",
schema = @Schema(implementation = ExceptionResponseMessage.class)))
})
ResponseEntity<?> listFunctions(
@Parameter(description = "Standard HTTP Accept-Language header")
@NotNull @RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) String acceptLanguage,
@Parameter(description = "Bearer access token")
@NotNull @RequestHeader(HttpHeaders.AUTHORIZATION) String authorization,
@Parameter(description = "The VIN of the vehicle")
@NotNull @PathVariable(Headers.VIN) String vin);
@GetMapping(value = {"/vehicles/{vin}/services"}, produces = {"application/vnd.example.functionlist.v2+json",
"application/vnd.example.error.v1+json"})
@Operation(description = "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service configuration data from the AEM config service.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Success", content = @Content(
mediaType = "application/vnd.example.functionlist.v2+json",
schema = @Schema(implementation = VehicleFunctionsListV2.class))),
@ApiResponse(responseCode = "403", description = "user is non paired guest user / anonymous and is not owner", content = @Content(
mediaType = "application/vnd.example.error.v1+json",
schema = @Schema(implementation = ExceptionResponseMessage.class))),
@ApiResponse(responseCode = "500", description = "Internal error during request execution", content = @Content(
mediaType = "application/vnd.example.error.v1+json",
schema = @Schema(implementation = ExceptionResponseMessage.class)))
})
ResponseEntity<?> listFunctionsV2(
@Parameter(description = "Standard HTTP Accept-Language header")
@NotNull @RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) String acceptLanguage,
@Parameter(description = "Bearer access token")
@NotNull @RequestHeader(HttpHeaders.AUTHORIZATION) String authorization,
@Parameter(description = "The VIN of the vehicle")
@NotNull @PathVariable(Headers.VIN) String vin);
@GetMapping(value = {"/vehicles/{vin}/services"}, produces = {"application/json",
"application/vnd.example.functionlist.v1+json", "application/vnd.example.error.v1+json"})
@Operation(description = "Gets a list of vehicle functions by calling the operation list for the vehicle and merging it with the service configuration data from the AEM config service.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Success", content = @Content(
mediaType = "application/vnd.example.functionlist.v1+json",
schema = @Schema(implementation = VehicleFunctionsListV1.class))),
@ApiResponse(responseCode = "200", description = "Success", content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = VehicleFunctionsListV1.class))),
@ApiResponse(responseCode = "403", description = "user is non paired guest user / anonymous and is not owner", content = @Content(
mediaType = "application/vnd.example.error.v1+json",
schema = @Schema(implementation = ExceptionResponseMessage.class))),
@ApiResponse(responseCode = "500", description = "Internal error during request execution", content = @Content(
mediaType = "application/vnd.example.error.v1+json",
schema = @Schema(implementation = ExceptionResponseMessage.class)))
})
ResponseEntity<?> listFunctionsV1(
@Parameter(description = "Standard HTTP Accept-Language header")
@NotNull @RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) String acceptLanguage,
@Parameter(description = "Bearer access token")
@NotNull @RequestHeader(HttpHeaders.AUTHORIZATION) String authorization,
@Parameter(description = "The VIN of the vehicle")
@NotNull @PathVariable(Headers.VIN) String vin);
}
any update on this ?