Reputation: 71
I am trying to generate OpenAPI (version 3.0.1) specification for my Java code. In order to achieve this I use Swagger Annotations (version 2.0.8) and Swagger Maven Plugin.
I have a problem with Enums. Say, I have two methods returning the very same Enum. In OpenAPI specification, I would like to have the single schema definition for this Enum and $ref
link in both API operations. But instead I have duplicated Enum definitions in each API operations. How do I avoid this duplication without editing specification file manually?
Here is Java code with two methods returning the same Enum:
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/properties")
@Produces("application/json")
public class TestService {
@GET
@Path("/enum1")
@Operation
@ApiResponses({
@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Color.class)))
})
public Color getColor1() {
throw new UnsupportedOperationException();
}
@GET
@Path("/enum2")
@Operation
@ApiResponses({
@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Color.class)))
})
public Color getColor2() {
throw new UnsupportedOperationException();
}
public enum Color {
RED,
GREEN,
BLUE
}
}
Here is specification I would like to get:
openapi: 3.0.1
components:
schemas:
Color:
type: string
enum:
- RED
- GREEN
- BLUE
paths:
/properties/enum2:
get:
operationId: getColor2
responses:
200:
content:
application/json:
schema:
$ref: '#/components/schemas/Color'
/properties/enum1:
get:
operationId: getColor1
responses:
200:
content:
application/json:
schema:
$ref: '#/components/schemas/Color'
And here is specification I do get:
openapi: 3.0.1
paths:
/properties/enum2:
get:
operationId: getColor2
responses:
200:
content:
application/json:
schema:
type: string
enum:
- RED
- GREEN
- BLUE
/properties/enum1:
get:
operationId: getColor1
responses:
200:
content:
application/json:
schema:
type: string
enum:
- RED
- GREEN
- BLUE
Upvotes: 8
Views: 5880
Reputation: 2795
I was facing the same issue with a Dropwizard application.
My model was something like this:
public class Model {
@Schema(name = "fields")
@Default
@NotNull
private Set<CustomEnum> fields = Collections.emptySet();
@Schema(name = "patches")
@Default
@NotNull
private Set<CustomEnum> patches = Collections.emptySet();
}
and my enum:
public enum CustomEnum {
COMPANY,
PERSON,
EMAIL
}
My approach was the following:
First, add the @Schema
annotation to the CustomEnum
enum:
@Schema(ref = "#/components/schemas/CustomEnumItem")
public enum CustomEnum {}
Note that I change the reference name to CustomEnumItem
.
Second, I registered the schema and swagger configuration programmatically:
OpenAPI oas =
new OpenAPI()
.info(getInfo())
.addServersItem(new Server().url(baseUrl));
var customEnumItem = new Schema<CustomEnum>();
customEnumItem.setType("string");
customEnumItem.setEnum(List.of(CustomEnum.values()));
oas.getComponents().addSchemas("CustomEnumItem", customEnumItem);
return new SwaggerConfiguration()
.openAPI(oas)
.readAllResources(true)
.prettyPrint(true);
So, my swagger.json file was generated like this:
"components" : {
"schemas" : {
"CustomEnumItem" : {
"type" : "string",
"enum" : [ "COMPANY", "PERSON", "EMAIL"]
},
"Model" : {
"required" : [ "fields", "patches"],
"type" : "object",
"properties" : {
"fields" : {
"uniqueItems" : true,
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/CustomEnumItem"
}
},
"patches" : {
"uniqueItems" : true,
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/CustomEnumItem"
}
},
And my generated client code like this:
public class Model {
@JsonProperty("fields")
private Set<CustomEnumItem> fields;
@JsonProperty("patches")
private Set<CustomEnumItem> patches;
Before this change I got something like this (two enums instead of one):
public class Model {
@JsonProperty("fields")
private Set<FieldsEnum> fields;
@JsonProperty("patches")
private Set<PatchesEnum> patches;
}
We can find the reference to reusable enums here.
Also as @david-karlsson mentioned enumAsRef
also works, but you need swagger annotations 2.1.0.
Upvotes: 1
Reputation: 61
Write a toString in the enum class (in my example ErrorClass). Swagger takes it automatically.
@ApiResponse(responseCode = "404",description = "Errors example",content = {
@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorClass.class)) }),
Upvotes: 0
Reputation: 9716
I am in kotlin but I added the (relatively new) @Schema(enumAsRef = true)
to the enum class with success.
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/properties")
@Produces("application/json")
public class TestService {
@GET
@Path("/enum1")
@Operation
@ApiResponses({
@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Color.class)))
})
public Color getColor1() {
throw new UnsupportedOperationException();
}
@GET
@Path("/enum2")
@Operation
@ApiResponses({
@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Color.class)))
})
public Color getColor2() {
throw new UnsupportedOperationException();
}
@Schema(enumAsRef = true) // THIS MAKES ENUM REF
public enum Color {
RED,
GREEN,
BLUE
}
}
Upvotes: 6