Swagger Core annotations library providing OpenAPI 3.x annotations for Java applications, enabling developers to document REST APIs with metadata annotations
—
This document covers the fundamental annotations for OpenAPI operation documentation, API definitions, parameters, and basic element configuration.
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.StringToClassMapItem;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.enums.ParameterStyle;
import io.swagger.v3.oas.annotations.enums.Explode;
import io.swagger.v3.oas.annotations.parameters.ValidatedParameter;Populates OpenAPI Object fields including info, tags, servers, security, and external documentation. Applied at the class or package level to define overall API characteristics.
@OpenAPIDefinition(
info = @Info(
title = "Pet Store API",
version = "1.0.0",
description = "A comprehensive pet store management API",
contact = @Contact(
name = "API Support",
url = "https://petstore.io/contact",
email = "support@petstore.io"
),
license = @License(
name = "Apache 2.0",
url = "https://www.apache.org/licenses/LICENSE-2.0.html"
)
),
tags = {
@Tag(name = "pets", description = "Pet operations"),
@Tag(name = "store", description = "Store operations"),
@Tag(name = "users", description = "User operations")
},
servers = {
@Server(
url = "https://api.petstore.io/v1",
description = "Production server"
),
@Server(
url = "https://staging.petstore.io/v1",
description = "Staging server"
)
},
security = @SecurityRequirement(name = "api_key"),
externalDocs = @ExternalDocumentation(
description = "Find more info here",
url = "https://petstore.io/docs"
)
)
@RestController
public class PetStoreApiController {
// API implementation
}public @interface OpenAPIDefinition {
Info info() default @Info;
Tag[] tags() default {};
Server[] servers() default {};
SecurityRequirement[] security() default {};
ExternalDocumentation externalDocs() default @ExternalDocumentation;
Extension[] extensions() default {};
}Defines a resource method as an OpenAPI Operation with comprehensive documentation including parameters, responses, security requirements, and metadata.
@Operation(
operationId = "getPetById",
summary = "Find pet by ID",
description = "Returns a single pet based on the provided ID. " +
"This endpoint requires authentication and validates the pet ID parameter.",
tags = {"pets"},
method = "GET",
parameters = {
@Parameter(
name = "id",
description = "ID of pet to return",
required = true,
in = ParameterIn.PATH,
schema = @Schema(type = "integer", format = "int64", minimum = "1")
)
},
responses = {
@ApiResponse(
responseCode = "200",
description = "Successful operation",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = Pet.class)
)
),
@ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
@ApiResponse(responseCode = "404", description = "Pet not found")
},
security = @SecurityRequirement(name = "api_key"),
deprecated = false,
hidden = false,
externalDocs = @ExternalDocumentation(
description = "Learn more about pet operations",
url = "https://petstore.io/docs/pets"
)
)
@GetMapping("/pets/{id}")
public ResponseEntity<Pet> getPetById(@PathVariable Long id) {
Pet pet = petService.findById(id);
return ResponseEntity.ok(pet);
}@Operation(
summary = "Update pet information",
description = "Update an existing pet's information with partial data",
requestBody = @RequestBody(
description = "Pet object with updated information",
required = true,
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = PetUpdateRequest.class),
examples = @ExampleObject(
name = "updatePetExample",
summary = "Example pet update",
value = "{ \"name\": \"Fluffy Updated\", \"status\": \"available\" }"
)
)
),
servers = {
@Server(url = "https://api.petstore.io/v1", description = "Primary server"),
@Server(url = "https://api-beta.petstore.io/v1", description = "Beta server")
},
extensions = {
@Extension(name = "x-rate-limit", properties = {
@ExtensionProperty(name = "requests", value = "100"),
@ExtensionProperty(name = "per", value = "minute")
})
},
ignoreJsonView = false
)
@PutMapping("/pets/{id}")
public ResponseEntity<Pet> updatePet(
@PathVariable Long id,
@Valid @RequestBody PetUpdateRequest request
) {
Pet updatedPet = petService.update(id, request);
return ResponseEntity.ok(updatedPet);
}public @interface Operation {
String method() default "";
String[] tags() default {};
String summary() default "";
String description() default "";
RequestBody requestBody() default @RequestBody();
ExternalDocumentation externalDocs() default @ExternalDocumentation();
String operationId() default "";
Parameter[] parameters() default {};
ApiResponse[] responses() default {};
boolean deprecated() default false;
SecurityRequirement[] security() default {};
Server[] servers() default {};
Extension[] extensions() default {};
boolean hidden() default false;
boolean ignoreJsonView() default false;
}Defines method parameters as operation parameters with comprehensive documentation, validation constraints, and serialization options.
@GetMapping("/pets")
@Operation(summary = "List pets with filtering options", tags = {"pets"})
public ResponseEntity<List<Pet>> listPets(
@Parameter(
name = "status",
description = "Status values to filter pets",
required = false,
in = ParameterIn.QUERY,
style = ParameterStyle.FORM,
explode = Explode.TRUE,
schema = @Schema(
type = "array",
allowableValues = {"available", "pending", "sold"}
),
examples = {
@ExampleObject(
name = "singleStatus",
summary = "Single status filter",
value = "available"
),
@ExampleObject(
name = "multipleStatuses",
summary = "Multiple status filters",
value = "available,pending"
)
}
)
@RequestParam(required = false) List<String> status,
@Parameter(
name = "category",
description = "Pet category ID for filtering",
required = false,
in = ParameterIn.QUERY,
schema = @Schema(type = "integer", format = "int64", minimum = "1"),
example = "1"
)
@RequestParam(required = false) Long category,
@Parameter(
name = "limit",
description = "Maximum number of pets to return",
required = false,
in = ParameterIn.QUERY,
schema = @Schema(
type = "integer",
format = "int32",
minimum = "1",
maximum = "100",
defaultValue = "20"
)
)
@RequestParam(defaultValue = "20") int limit,
@Parameter(
name = "X-Request-ID",
description = "Unique request identifier for tracking",
required = false,
in = ParameterIn.HEADER,
schema = @Schema(type = "string", format = "uuid"),
example = "123e4567-e89b-12d3-a456-426614174000"
)
@RequestHeader(value = "X-Request-ID", required = false) String requestId
) {
List<Pet> pets = petService.findByFilters(status, category, limit);
return ResponseEntity.ok(pets);
}// Matrix parameter style example
@Parameter(
name = "coordinates",
in = ParameterIn.PATH,
style = ParameterStyle.MATRIX,
explode = Explode.TRUE,
schema = @Schema(type = "object"),
description = "Geographic coordinates in matrix style"
)
// Label parameter style example
@Parameter(
name = "tags",
in = ParameterIn.PATH,
style = ParameterStyle.LABEL,
explode = Explode.FALSE,
schema = @Schema(type = "array", items = @Schema(type = "string")),
description = "Pet tags in label style"
)
// Deep object parameter style
@Parameter(
name = "filter",
in = ParameterIn.QUERY,
style = ParameterStyle.DEEPOBJECT,
explode = Explode.TRUE,
schema = @Schema(implementation = PetFilter.class),
description = "Complex filter object"
)@Parameter(
name = "metadata",
description = "Complex metadata object",
required = false,
in = ParameterIn.QUERY,
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = PetMetadata.class),
examples = @ExampleObject(
name = "metadataExample",
value = "{ \"source\": \"web\", \"version\": \"1.0\" }"
)
)
}
)public @interface Parameter {
String name() default "";
ParameterIn in() default ParameterIn.DEFAULT;
String description() default "";
boolean required() default false;
boolean deprecated() default false;
boolean allowEmptyValue() default false;
ParameterStyle style() default ParameterStyle.DEFAULT;
Explode explode() default Explode.DEFAULT;
boolean allowReserved() default false;
Schema schema() default @Schema();
ArraySchema array() default @ArraySchema();
Content[] content() default {};
boolean hidden() default false;
ExampleObject[] examples() default {};
String example() default "";
Extension[] extensions() default {};
String ref() default "";
Class<?>[] validationGroups() default {};
}Container annotation for multiple @Parameter annotations when applied at the method level.
@Parameters({
@Parameter(
name = "X-API-Version",
description = "API version header",
in = ParameterIn.HEADER,
schema = @Schema(type = "string", defaultValue = "1.0")
),
@Parameter(
name = "Accept-Language",
description = "Preferred language for response",
in = ParameterIn.HEADER,
schema = @Schema(type = "string", defaultValue = "en-US")
)
})
@GetMapping("/pets/{id}")
public ResponseEntity<Pet> getPetById(@PathVariable Long id) {
return ResponseEntity.ok(petService.findById(id));
}Marks resources, classes, or bean properties as hidden, causing them to be excluded from OpenAPI documentation generation.
// Hide entire controller
@Hidden
@RestController
public class InternalController {
// This entire controller will be excluded from documentation
}
// Hide specific operation
@GetMapping("/pets/{id}/internal-data")
@Hidden
public ResponseEntity<String> getInternalData(@PathVariable Long id) {
// This operation will be excluded from documentation
}
// Hide specific parameter
public ResponseEntity<Pet> createPet(
@Parameter(description = "Pet data") @RequestBody Pet pet,
@Hidden @RequestParam String internalFlag // Hidden from docs
) {
return ResponseEntity.ok(petService.create(pet));
}@Schema(description = "User profile information")
public class User {
@Schema(description = "User ID")
private Long id;
@Schema(description = "User name")
private String name;
@Hidden // This field will not appear in the schema
private String internalNotes;
@Schema(description = "User email", format = "email")
private String email;
}Adds references to external resources for extended documentation, commonly used with operations, schemas, and API definitions.
@Operation(
summary = "Complex pet operation",
description = "A complex operation with detailed external documentation",
externalDocs = @ExternalDocumentation(
description = "Detailed operation guide with examples and troubleshooting",
url = "https://petstore.io/docs/operations/complex-pet-operation",
extensions = @Extension(name = "x-doc-type", properties = {
@ExtensionProperty(name = "type", value = "guide"),
@ExtensionProperty(name = "level", value = "advanced")
})
)
)
@PostMapping("/pets/complex-operation")
public ResponseEntity<Pet> complexPetOperation(@RequestBody ComplexPetRequest request) {
return ResponseEntity.ok(petService.performComplexOperation(request));
}@Schema(
description = "Pet information model",
externalDocs = @ExternalDocumentation(
description = "Pet data model specification and examples",
url = "https://petstore.io/docs/schemas/pet"
)
)
public class Pet {
// Pet fields
}public @interface ExternalDocumentation {
String description() default "";
String url() default "";
Extension[] extensions() default {};
}Utility annotation for creating string-to-class mappings, typically used in complex annotation configurations that require dynamic class mapping.
// Example usage in custom configurations
@StringToClassMapItem(key = "Pet", value = Pet.class)
@StringToClassMapItem(key = "Category", value = Category.class)
@StringToClassMapItem(key = "User", value = User.class)
public class SchemaRegistry {
// Class mapping configuration
}public @interface StringToClassMapItem {
String key();
Class<?> value();
}Defines the location of a parameter in the HTTP request.
public enum ParameterIn {
DEFAULT(""),
HEADER("header"),
QUERY("query"),
PATH("path"),
COOKIE("cookie");
}Defines how parameter values are serialized based on the parameter type and location.
public enum ParameterStyle {
DEFAULT, // Empty string ""
MATRIX, // Matrix style for path parameters - "matrix"
LABEL, // Label style for path parameters - "label"
FORM, // Form style for query and cookie parameters - "form"
SPACEDELIMITED, // Space separated values - "spaceDelimited"
PIPEDELIMITED, // Pipe separated values - "pipeDelimited"
DEEPOBJECT, // Deep object serialization for query parameters - "deepObject"
SIMPLE // Simple style for path and header parameters - "simple"
}Defines whether parameter values should be exploded (separated) or not.
public enum Explode {
DEFAULT,
TRUE, // Parameter values are separated
FALSE // Parameter values are not separated
}// Query parameter with form style and exploded values
@Parameter(
name = "tags",
in = ParameterIn.QUERY,
style = ParameterStyle.FORM,
explode = Explode.TRUE,
schema = @Schema(type = "array", items = @Schema(type = "string"))
)
// Results in: ?tags=tag1&tags=tag2&tags=tag3
// Query parameter with form style and non-exploded values
@Parameter(
name = "tags",
in = ParameterIn.QUERY,
style = ParameterStyle.FORM,
explode = Explode.FALSE,
schema = @Schema(type = "array", items = @Schema(type = "string"))
)
// Results in: ?tags=tag1,tag2,tag3
// Path parameter with matrix style
@Parameter(
name = "coordinates",
in = ParameterIn.PATH,
style = ParameterStyle.MATRIX,
explode = Explode.TRUE,
schema = @Schema(type = "object")
)
// Results in: /path;lat=50.1;lng=14.4
// Cookie parameter
@Parameter(
name = "sessionId",
in = ParameterIn.COOKIE,
required = true,
schema = @Schema(type = "string", format = "uuid")
)Defines validation groups for parameter validation using Bean Validation (JSR 303/349/380) annotations.
// Define validation groups
public interface CreateValidation {}
public interface UpdateValidation {}
@RestController
public class PetController {
@PostMapping("/pets")
@Operation(summary = "Create pet with validation")
public ResponseEntity<Pet> createPet(
@ValidatedParameter(groups = CreateValidation.class)
@Parameter(
description = "Pet data for creation",
required = true,
schema = @Schema(implementation = CreatePetRequest.class)
)
@Valid @RequestBody CreatePetRequest request
) {
return ResponseEntity.ok(petService.create(request));
}
@PutMapping("/pets/{id}")
@Operation(summary = "Update pet with validation")
public ResponseEntity<Pet> updatePet(
@PathVariable Long id,
@ValidatedParameter(groups = UpdateValidation.class)
@Parameter(
description = "Pet data for update",
required = true,
schema = @Schema(implementation = UpdatePetRequest.class)
)
@Valid @RequestBody UpdatePetRequest request
) {
return ResponseEntity.ok(petService.update(id, request));
}
}// Validation group interfaces
public interface BasicValidation {}
public interface AdvancedValidation {}
public interface AdminValidation {}
@PostMapping("/pets/advanced")
@Operation(summary = "Create pet with advanced validation")
public ResponseEntity<Pet> createAdvancedPet(
@ValidatedParameter(groups = {BasicValidation.class, AdvancedValidation.class})
@Parameter(
description = "Advanced pet creation request",
schema = @Schema(implementation = AdvancedPetRequest.class)
)
@Valid @RequestBody AdvancedPetRequest request
) {
return ResponseEntity.ok(petService.createAdvanced(request));
}
// Request class with validation groups
@Schema(description = "Advanced pet creation request")
public class AdvancedPetRequest {
@NotBlank(groups = BasicValidation.class)
@Size(min = 2, max = 50, groups = BasicValidation.class)
@Schema(description = "Pet name")
private String name;
@NotNull(groups = AdvancedValidation.class)
@Valid(groups = AdvancedValidation.class)
@Schema(description = "Advanced pet characteristics")
private PetCharacteristics characteristics;
@NotNull(groups = AdminValidation.class)
@Schema(description = "Internal system identifier")
private String internalId;
}@RestController
public class ConditionalValidationController {
@PostMapping("/pets/conditional")
@Operation(summary = "Create pet with conditional validation")
public ResponseEntity<Pet> createConditionalPet(
@ValidatedParameter(groups = {
BasicValidation.class,
ConditionalValidation.class
})
@Parameter(
description = "Pet creation with conditional requirements",
schema = @Schema(implementation = ConditionalPetRequest.class)
)
@Valid @RequestBody ConditionalPetRequest request,
@Parameter(
description = "Validation level",
in = ParameterIn.QUERY,
schema = @Schema(
type = "string",
allowableValues = {"basic", "advanced", "strict"},
defaultValue = "basic"
)
)
@RequestParam(defaultValue = "basic") String validationLevel
) {
// Validation logic based on level
return ResponseEntity.ok(petService.createWithValidation(request, validationLevel));
}
}
// Conditional validation groups
public interface ConditionalValidation {}
@Schema(description = "Pet request with conditional validation")
public class ConditionalPetRequest {
@NotBlank(groups = BasicValidation.class)
@Schema(description = "Pet name", required = true)
private String name;
@NotNull(groups = ConditionalValidation.class)
@Min(value = 0, groups = ConditionalValidation.class)
@Max(value = 50, groups = ConditionalValidation.class)
@Schema(description = "Pet age (required for advanced validation)")
private Integer age;
@Valid(groups = ConditionalValidation.class)
@Schema(description = "Health information (required for strict validation)")
private HealthInfo healthInfo;
}public @interface ValidatedParameter {
Class<?>[] groups() default {}; // Validation groups to apply
Class<?>[] value() default {}; // Alias for groups
}Install with Tessl CLI
npx tessl i tessl/maven-io-swagger-core-v3--swagger-annotations