-
-
Couldn't load subscription status.
- Fork 551
Description
Is your feature request related to a problem? Please describe.
The Jakarta bean validation standard allows constraint composition: https://beanvalidation.org/2.0/spec/#constraintsdefinitionimplementation-constraintcomposition. Constraint composition is a nice way of building reusable validation rules to use throughout an application. This decreases the amount of duplication and ensures that the specification of multiple fields is always in sync. It also allows for attaching functional names to combinations of validations.
For example, an identifier for use in a URL can be validated as follows:
@NotNull
@Pattern(regexp = "[A-Za-z0-9-]{8,12}")
@Size(min = 8, max = 12)
@Constraint(validatedBy = {})
@Documented
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
public @interface ValidIdentifier {
String message() default "must be a valid identifier";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Value
public class Example {
@ValidIdentifier
@Schema(required = true, description = "Unique identifier")
String identifier;
}In the generated OpenAPI file, this looks as follows:
"Example": {
"required": ["identifier"],
"type": "object",
"properties": {
"identifier": {
"type": "string",
"description": "Unique identifier"
}
}
}At the moment, the constraints placed on the @ValidIdentifier composite do not end up in the OpenAPI specification.
I am using springdoc 13.0.2 and swagger-core 2.1.12.
Describe the solution you'd like
It would be great if constraint annotations can be parsed recursively. Effectively, given a tree-like structure of annotations, this should be flattened into a single list of constraints.
For the example above, reasoning can be as follows:
- Consider the supported bean validation annotations on the field. In this example, there are none.
- Consider the annotations on the field that are annotated with
@Constraint. In this example, there is@ValidIdentifier.- For each such annotation, repeat the above process. (Consider the supported bean validation annotations, and try to find other
@Constraintannotations which could have supported bean validation annotations on them.
- For each such annotation, repeat the above process. (Consider the supported bean validation annotations, and try to find other
After processing the above example, the result should be equivalent to the following Java code:
@Value
public class Example {
@NotNull
@Pattern(regexp = "^[A-Za-z0-9-]{8,12}$")
@Size(min = 8, max = 12)
@Schema(required = true, description = "Unique identifier")
String identifier;
}The generated OpenAPI file should contain additional constraints:
"Example": {
"required": ["identifier"],
"type": "object",
"properties": {
"identifier": {
"type": "string",
"description": "Unique identifier",
"pattern": "^[A-Za-z0-9-]{8,12}$",
"minLength": 8,
"maxLength": 12
}
}
}Describe alternatives you've considered
Alternatively is not using constraint composition and specifying constraints on each field separately. This would lead to code duplication, and may cause validations to become slightly different over time, as it is difficult to update each separate location when a change needs to be made.
Additional context
None.