From f778e97e20ab5824f8b0d277e577ee8fe14dc68c Mon Sep 17 00:00:00 2001 From: altro3 Date: Wed, 25 Sep 2024 19:41:35 +0700 Subject: [PATCH] Add support validation annotations extensions. --- .../io/micronaut/openapi/generator/Utils.java | 93 +++++- .../common/params/validation.mustache | 34 +- .../common/params/validation.mustache | 34 +- .../common/params/validation_field.mustache | 36 +-- .../JavaMicronautClientCodegenTest.java | 149 +++++++++ .../JavaMicronautServerCodegenTest.java | 44 +++ .../KotlinMicronautClientCodegenTest.java | 148 +++++++++ .../KotlinMicronautServerCodegenTest.java | 43 +++ .../resources/3_0/validation-messages.yml | 292 ++++++++++++++++++ 9 files changed, 809 insertions(+), 64 deletions(-) create mode 100644 openapi-generator/src/test/resources/3_0/validation-messages.yml diff --git a/openapi-generator/src/main/java/io/micronaut/openapi/generator/Utils.java b/openapi-generator/src/main/java/io/micronaut/openapi/generator/Utils.java index 9f7daca204..97ac909494 100644 --- a/openapi-generator/src/main/java/io/micronaut/openapi/generator/Utils.java +++ b/openapi-generator/src/main/java/io/micronaut/openapi/generator/Utils.java @@ -156,20 +156,34 @@ private static String genericAnnotations(CodegenProperty prop, boolean isGenerat return result.toString(); } + var patternMsg = (String) prop.vendorExtensions.get("x-pattern-message"); + var sizeMsg = (String) prop.vendorExtensions.get("x-size-message"); + var notNullMsg = (String) prop.vendorExtensions.get("x-not-null-message"); + var minMsg = (String) prop.vendorExtensions.get("x-min-message"); + var maxMsg = (String) prop.vendorExtensions.get("x-max-message"); + if (StringUtils.isNotEmpty(prop.pattern) && !prop.isDate && !prop.isDateTime) { - if ("email".equals(type)) { + if ("email".equals(type) || "email".equalsIgnoreCase(prop.dataFormat) || prop.isEmail) { result.append("@Email(regexp = \""); } else { result.append("@Pattern(regexp = \""); } - result.append(prop.pattern).append("\") "); + result.append(prop.pattern).append("\""); + if (patternMsg != null) { + result.append(", message = \"").append(patternMsg).append("\""); + } + result.append(") "); } var containsNotEmpty = false; if (prop.minLength != null || prop.maxLength != null) { if (prop.minLength != null && prop.minLength == 1 && prop.maxLength == null && !prop.isNullable) { - result.append("@NotEmpty "); + result.append("@NotEmpty"); + if (sizeMsg != null) { + result.append("(message = \"").append(sizeMsg).append("\")"); + } + result.append(' '); containsNotEmpty = true; } else { result.append("@Size("); @@ -182,6 +196,9 @@ private static String genericAnnotations(CodegenProperty prop, boolean isGenerat } result.append("max = ").append(prop.maxLength); } + if (sizeMsg != null) { + result.append(", message = \"").append(sizeMsg).append('"'); + } result.append(") "); } } @@ -201,6 +218,9 @@ private static String genericAnnotations(CodegenProperty prop, boolean isGenerat } result.append("max = ").append(prop.maxItems); } + if (sizeMsg != null) { + result.append(", message = \"").append(sizeMsg).append('"'); + } result.append(") "); } } @@ -212,7 +232,11 @@ private static String genericAnnotations(CodegenProperty prop, boolean isGenerat result.append("@Nullable "); } } else if (!containsNotEmpty) { - result.append("@NotNull "); + result.append("@NotNull"); + if (notNullMsg != null) { + result.append("(message = \"").append(notNullMsg).append("\")"); + } + result.append(" "); } } if (StringUtils.isNotEmpty(prop.minimum)) { @@ -222,21 +246,43 @@ private static String genericAnnotations(CodegenProperty prop, boolean isGenerat longNumber++; } if (longNumber == 0 && StringUtils.isEmpty(prop.maximum)) { - result.append("@PositiveOrZero "); + result.append("@PositiveOrZero"); + if (minMsg != null) { + result.append("(message = \"").append(minMsg).append("\")"); + } + result.append(" "); } else if (longNumber == 1 && StringUtils.isEmpty(prop.maximum)) { - result.append("@Positive "); + result.append("@Positive"); + if (minMsg != null) { + result.append("(message = \"").append(minMsg).append("\")"); + } + result.append(" "); } else { - result.append("@Min(").append(longNumber).append(") "); + result.append("@Min("); + if (minMsg != null) { + result.append("value = "); + } + result.append(longNumber); + if (prop.isLong) { + result.append("L"); + } + if (minMsg != null) { + result.append(", message = \"").append(minMsg).append("\""); + } + result.append(") "); } } catch (Exception e) { result.append("@DecimalMin("); - if (prop.exclusiveMinimum) { + if (prop.exclusiveMinimum || minMsg != null) { result.append("value = "); } result.append('"').append(prop.minimum).append('"'); if (prop.exclusiveMinimum) { result.append(", inclusive = false"); } + if (minMsg != null) { + result.append(", message = \"").append(minMsg).append("\""); + } result.append(") "); } } @@ -247,21 +293,44 @@ private static String genericAnnotations(CodegenProperty prop, boolean isGenerat longNumber--; } if (longNumber == 0 && StringUtils.isEmpty(prop.minimum)) { - result.append("@NegativeOrZero "); + result.append("@NegativeOrZero"); + if (maxMsg != null) { + result.append("(message = \"").append(maxMsg).append("\")"); + } + result.append(" "); } else if (longNumber == -1 && StringUtils.isEmpty(prop.minimum)) { - result.append("@Negative "); + result.append("@Negative"); + if (maxMsg != null) { + result.append("(message = \"").append(maxMsg).append("\")"); + } + result.append(" "); } else { - result.append("@Max(").append(longNumber).append(") "); + result.append("@Max("); + if (maxMsg != null) { + result.append("value = "); + } + result.append(longNumber); + if (prop.isLong) { + result.append("L"); + } + if (maxMsg != null) { + result.append(", message = \"").append(maxMsg).append("\""); + } + result.append(") "); + } } catch (Exception e) { result.append("@DecimalMax("); - if (prop.exclusiveMaximum) { + if (prop.exclusiveMaximum || maxMsg != null) { result.append("value = "); } result.append('"').append(prop.maximum).append('"'); if (prop.exclusiveMaximum) { result.append(", inclusive = false"); } + if (maxMsg != null) { + result.append(", message = \"").append(maxMsg).append("\""); + } result.append(") "); } } diff --git a/openapi-generator/src/main/resources/templates/java-micronaut/common/params/validation.mustache b/openapi-generator/src/main/resources/templates/java-micronaut/common/params/validation.mustache index 29e017b88c..e8b930ca8b 100644 --- a/openapi-generator/src/main/resources/templates/java-micronaut/common/params/validation.mustache +++ b/openapi-generator/src/main/resources/templates/java-micronaut/common/params/validation.mustache @@ -37,7 +37,7 @@ {{^isNullable}} {{#required}} {{^isReadOnly}} - @NotNull + @NotNull{{#vendorExtensions.x-not-null-message}}(message = "{{{.}}}"){{/vendorExtensions.x-not-null-message}} {{/isReadOnly}} {{/required}} {{/isNullable}} @@ -50,63 +50,63 @@ {{/isContainer}} {{!Pattern}} {{#pattern}} - {{^isByteArray}}{{^isDate}}{{^isDateTime}} - @Pattern(regexp = "{{{pattern}}}") - {{/isDateTime}}{{/isDate}}{{/isByteArray}} + {{^isEmail}}{{^isByteArray}}{{^isDate}}{{^isDateTime}} + @Pattern(regexp = "{{{pattern}}}"{{#vendorExtensions.x-pattern-message}}, message = "{{{.}}}"{{/vendorExtensions.x-pattern-message}}) + {{/isDateTime}}{{/isDate}}{{/isByteArray}}{{/isEmail}} {{/pattern}} {{!Min length && max length}} {{#minLength}} {{#maxLength}} - @Size(min = {{minLength}}, max = {{maxLength}}) + @Size(min = {{minLength}}, max = {{maxLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}} {{/minLength}} {{#minLength}}{{^maxLength}} - @Size(min = {{minLength}}) + @Size(min = {{minLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}}{{/minLength}} {{^minLength}}{{#maxLength}} - @Size(max = {{maxLength}}) + @Size(max = {{maxLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}}{{/minLength}} {{!Size}} {{#minItems}}{{#maxItems}} - @Size(min = {{minItems}}, max = {{maxItems}}) + @Size(min = {{minItems}}, max = {{maxItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{#minItems}}{{^maxItems}} - @Size(min = {{minItems}}) + @Size(min = {{minItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{^minItems}}{{#maxItems}} - @Size(max = {{maxItems}}) + @Size(max = {{maxItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{!Email}} {{#isEmail}} - @Email + @Email{{#pattern}}(regexp = "{{{pattern}}}"{{#vendorExtensions.x-pattern-message}}, message = "{{{.}}}"{{/vendorExtensions.x-pattern-message}}){{/pattern}}{{^pattern}}{{#vendorExtensions.x-pattern-message}}(message = "{{{.}}}"){{/vendorExtensions.x-pattern-message}}{{/pattern}} {{/isEmail}} {{!check for integer or long / all others=decimal type with @Decimal isInteger set}} {{#isInteger}} {{#minimum}} - @Min({{minimum}}) + @Min({{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{{.}}}{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{#maximum}} - @Max({{maximum}}) + @Max({{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{{.}}}{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isInteger}} {{!isLong set}} {{#isLong}} {{#minimum}} - @Min({{minimum}}L) + @Min({{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{{.}}}L{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{#maximum}} - @Max({{maximum}}L) + @Max({{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{{.}}}L{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isLong}} {{!Not Integer, not Long => we have a decimal value!}} {{^isInteger}} {{^isLong}}{{!minimum for decimal value}} {{#minimum}} - @DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}) + @DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}{{^exclusiveMinimum}}{{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{!maximal for decimal value}} {{#maximum}} - @DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}) + @DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}{{^exclusiveMaximum}}{{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isLong}} {{/isInteger}} diff --git a/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation.mustache b/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation.mustache index 85c0c13486..460c35d3fb 100644 --- a/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation.mustache +++ b/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation.mustache @@ -17,7 +17,7 @@ {{^isNullable}} {{#required}} {{^isReadOnly}} - @NotNull + @NotNull{{#vendorExtensions.x-not-null-message}}(message = "{{{.}}}"){{/vendorExtensions.x-not-null-message}} {{/isReadOnly}} {{/required}} {{/isNullable}} @@ -30,63 +30,63 @@ {{/isContainer}} {{!Pattern}} {{#pattern}} - {{^isByteArray}}{{^isDate}}{{^isDateTime}} - @Pattern(regexp = "{{{pattern}}}") - {{/isDateTime}}{{/isDate}}{{/isByteArray}} + {{^isEmail}}{{^isByteArray}}{{^isDate}}{{^isDateTime}} + @Pattern(regexp = "{{{pattern}}}"{{#vendorExtensions.x-pattern-message}}, message = "{{{.}}}"{{/vendorExtensions.x-pattern-message}}) + {{/isDateTime}}{{/isDate}}{{/isByteArray}}{{/isEmail}} {{/pattern}} {{!Min length && max length}} {{#minLength}} {{#maxLength}} - @Size(min = {{minLength}}, max = {{maxLength}}) + @Size(min = {{minLength}}, max = {{maxLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}} {{/minLength}} {{#minLength}}{{^maxLength}} - @Size(min = {{minLength}}) + @Size(min = {{minLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}}{{/minLength}} {{^minLength}}{{#maxLength}} - @Size(max = {{maxLength}}) + @Size(max = {{maxLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}}{{/minLength}} {{!Size}} {{#minItems}}{{#maxItems}} - @Size(min = {{minItems}}, max = {{maxItems}}) + @Size(min = {{minItems}}, max = {{maxItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{#minItems}}{{^maxItems}} - @Size(min = {{minItems}}) + @Size(min = {{minItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{^minItems}}{{#maxItems}} - @Size(max = {{maxItems}}) + @Size(max = {{maxItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{!Email}} {{#isEmail}} - @Email + @Email{{#pattern}}(regexp = "{{{pattern}}}"{{#vendorExtensions.x-pattern-message}}, message = "{{{.}}}"{{/vendorExtensions.x-pattern-message}}){{/pattern}}{{^pattern}}{{#vendorExtensions.x-pattern-message}}(message = "{{{.}}}"){{/vendorExtensions.x-pattern-message}}{{/pattern}} {{/isEmail}} {{!check for integer or long / all others=decimal type with @Decimal isInteger set}} {{#isInteger}} {{#minimum}} - @Min({{minimum}}) + @Min({{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{{.}}}{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{#maximum}} - @Max({{maximum}}) + @Max({{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{{.}}}{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isInteger}} {{!isLong set}} {{#isLong}} {{#minimum}} - @Min({{minimum}}L) + @Min({{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{{.}}}L{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{#maximum}} - @Max({{maximum}}L) + @Max({{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{{.}}}L{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isLong}} {{!Not Integer, not Long => we have a decimal value!}} {{^isInteger}} {{^isLong}}{{!minimum for decimal value}} {{#minimum}} - @DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}) + @DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}{{^exclusiveMinimum}}{{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{!maximal for decimal value}} {{#maximum}} - @DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}) + @DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}{{^exclusiveMaximum}}{{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isLong}} {{/isInteger}} diff --git a/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation_field.mustache b/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation_field.mustache index ee22a4199b..a67a595b65 100644 --- a/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation_field.mustache +++ b/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/params/validation_field.mustache @@ -17,12 +17,12 @@ {{^isNullable}} {{#required}} {{^isReadOnly}} - @{{{vendorExtensions.fieldAnnPrefix}}}NotNull + @{{{vendorExtensions.fieldAnnPrefix}}}NotNull{{#vendorExtensions.x-not-null-message}}(message = "{{{.}}}"){{/vendorExtensions.x-not-null-message}} {{/isReadOnly}} {{/required}} {{/isNullable}} - {{^isUuid}} {{!Validate all pojos and enums}} + {{^isUuid}} {{^isContainer}} {{#isModel}} @{{{vendorExtensions.fieldAnnPrefix}}}Valid @@ -30,63 +30,63 @@ {{/isContainer}} {{!Pattern}} {{#pattern}} - {{^isByteArray}} - @{{{vendorExtensions.fieldAnnPrefix}}}Pattern(regexp = "{{{pattern}}}") - {{/isByteArray}} + {{^isEmail}}{{^isByteArray}}{{^isDate}}{{^isDateTime}} + @{{{vendorExtensions.fieldAnnPrefix}}}Pattern(regexp = "{{{pattern}}}"{{#vendorExtensions.x-pattern-message}}, message = "{{{.}}}"{{/vendorExtensions.x-pattern-message}}) + {{/isDateTime}}{{/isDate}}{{/isByteArray}}{{/isEmail}} {{/pattern}} {{!Min length && max length}} {{#minLength}} {{#maxLength}} - @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minLength}}, max = {{maxLength}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minLength}}, max = {{maxLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}} {{/minLength}} {{#minLength}}{{^maxLength}} - @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minLength}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}}{{/minLength}} {{^minLength}}{{#maxLength}} - @{{{vendorExtensions.fieldAnnPrefix}}}Size(max = {{maxLength}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Size(max = {{maxLength}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxLength}}{{/minLength}} {{!Size}} {{#minItems}}{{#maxItems}} - @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minItems}}, max = {{maxItems}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minItems}}, max = {{maxItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{#minItems}}{{^maxItems}} - @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minItems}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Size(min = {{minItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{^minItems}}{{#maxItems}} - @{{{vendorExtensions.fieldAnnPrefix}}}Size(max = {{maxItems}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Size(max = {{maxItems}}{{#vendorExtensions.x-size-message}}, message = "{{{.}}}"{{/vendorExtensions.x-size-message}}) {{/maxItems}}{{/minItems}} {{!Email}} {{#isEmail}} - @{{{vendorExtensions.fieldAnnPrefix}}}Email + @{{{vendorExtensions.fieldAnnPrefix}}}Email{{#pattern}}(regexp = "{{{pattern}}}"{{#vendorExtensions.x-pattern-message}}, message = "{{{.}}}"{{/vendorExtensions.x-pattern-message}}){{/pattern}}{{^pattern}}{{#vendorExtensions.x-pattern-message}}(message = "{{{.}}}"){{/vendorExtensions.x-pattern-message}}{{/pattern}} {{/isEmail}} {{!check for integer or long / all others=decimal type with @Decimal isInteger set}} {{#isInteger}} {{#minimum}} - @{{{vendorExtensions.fieldAnnPrefix}}}Min({{minimum}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Min({{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{{.}}}{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{#maximum}} - @{{{vendorExtensions.fieldAnnPrefix}}}Max({{maximum}}) + @{{{vendorExtensions.fieldAnnPrefix}}}Max({{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{{.}}}{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isInteger}} {{!isLong set}} {{#isLong}} {{#minimum}} - @{{{vendorExtensions.fieldAnnPrefix}}}Min({{minimum}}L) + @{{{vendorExtensions.fieldAnnPrefix}}}Min({{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{{.}}}L{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{#maximum}} - @{{{vendorExtensions.fieldAnnPrefix}}}Max({{maximum}}L) + @{{{vendorExtensions.fieldAnnPrefix}}}Max({{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{{.}}}L{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isLong}} {{!Not Integer, not Long => we have a decimal value!}} {{^isInteger}} {{^isLong}}{{!minimum for decimal value}} {{#minimum}} - @{{{vendorExtensions.fieldAnnPrefix}}}DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}) + @{{{vendorExtensions.fieldAnnPrefix}}}DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}{{^exclusiveMinimum}}{{#vendorExtensions.x-min-message}}value = {{/vendorExtensions.x-min-message}}{{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}{{#vendorExtensions.x-min-message}}, message = "{{{.}}}"{{/vendorExtensions.x-min-message}}) {{/minimum}} {{!maximal for decimal value}} {{#maximum}} - @{{{vendorExtensions.fieldAnnPrefix}}}DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}) + @{{{vendorExtensions.fieldAnnPrefix}}}DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}{{^exclusiveMaximum}}{{#vendorExtensions.x-max-message}}value = {{/vendorExtensions.x-max-message}}{{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}{{#vendorExtensions.x-max-message}}, message = "{{{.}}}"{{/vendorExtensions.x-max-message}}) {{/maximum}} {{/isLong}} {{/isInteger}} diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java index be4cf3d08c..c53cbcfcfa 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java @@ -1040,4 +1040,153 @@ void testPrimitives() { "private List<@NotNull Long> longTypes" ); } + + @Test + void testCustomValidationMessages() { + + var codegen = new JavaMicronautClientCodegen(); + codegen.setUseEnumCaseInsensitive(true); + String outputPath = generateFiles(codegen, "src/test/resources/3_0/validation-messages.yml", CodegenConstants.APIS, CodegenConstants.MODELS); + String path = outputPath + "src/main/java/org/openapitools/"; + + assertFileContains(path + "api/BooksApi.java", + """ + @QueryValue("emailParam") @NotNull List<@Email(regexp = "email@dot.com", message = "This is email pattern message") @Size(min = 5, max = 10, message = "This is min max email length message") @NotNull(message = "This is required email message") String> emailParam, + """, + """ + @QueryValue("strParam") @NotNull List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String> strParam, + """, + """ + @QueryValue("strParam2") @NotNull List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, message = "This is min max string length message") @NotNull(message = "This is required string message") String> strParam2, + """, + """ + @QueryValue("strParam3") @NotNull List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String> strParam3, + """, + """ + @QueryValue("intParam") @NotNull List<@NotNull(message = "This is required int message") @Min(value = 5, message = "This is min message") @Max(value = 10, message = "This is max message") Integer> intParam, + """, + """ + @QueryValue("decimalParam") @NotNull List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", message = "This is decimal min message") @DecimalMax(value = "10.5", message = "This is decimal max message") BigDecimal> decimalParam, + """, + """ + @QueryValue("decimalParam2") @NotNull(message = "This is required param message") List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", inclusive = false, message = "This is decimal min message") @DecimalMax(value = "10.5", inclusive = false, message = "This is decimal max message") BigDecimal> decimalParam2, + """, + """ + @QueryValue("positiveParam") @NotNull List<@NotNull(message = "This is required int message") @Positive(message = "This is positive message") Integer> positiveParam, + """, + """ + @QueryValue("positiveOrZeroParam") @NotNull List<@NotNull(message = "This is required int message") @PositiveOrZero(message = "This is positive or zero message") Integer> positiveOrZeroParam, + """, + """ + @QueryValue("negativeParam") @NotNull List<@NotNull(message = "This is required int message") @Negative(message = "This is negative message") Integer> negativeParam, + """, + """ + @QueryValue("negativeOrZeroParam") @NotNull List<@NotNull(message = "This is required int message") @NegativeOrZero(message = "This is negative or zero message") Integer> negativeOrZeroParam, + """); + + assertFileContains(path + "model/Book.java", + """ + @NotNull(message = "This is required string message") + @Pattern(regexp = "[a-zA-Z ]+", message = "This is string pattern message") + @Size(min = 5, max = 10, message = "This is min max string length message") + @JsonProperty(JSON_PROPERTY_STR_PROP) + private String strProp; + """, + """ + @Nullable + @Pattern(regexp = "[a-zA-Z ]+", message = "This is string pattern message") + @Size(min = 5, message = "This is min string length message") + @JsonProperty(JSON_PROPERTY_STR_PROP2) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private String strProp2; + """, + """ + @Nullable + @Pattern(regexp = "[a-zA-Z ]+", message = "This is string pattern message") + @Size(max = 10, message = "This is min string length message") + @JsonProperty(JSON_PROPERTY_STR_PROP3) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private String strProp3; + """, + """ + @NotNull(message = "This is required email message") + @Size(min = 5, max = 10, message = "This is min max email length message") + @Email(regexp = "email@dot.com", message = "This is email pattern message") + @JsonProperty(JSON_PROPERTY_EMAIL_PROP) + private String emailProp; + """, + """ + @NotNull(message = "This is required int message") + @Min(value = 5, message = "This is min message") + @Max(value = 10, message = "This is max message") + @JsonProperty(JSON_PROPERTY_INT_PROP) + private Integer intProp; + """, + """ + @Nullable + @Min(value = 0, message = "This is positive message") + @JsonProperty(JSON_PROPERTY_POSITIVE_PROP) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private Integer positiveProp; + """, + """ + @Nullable + @Min(value = 0, message = "This is positive or zero message") + @JsonProperty(JSON_PROPERTY_POSITIVE_OR_ZERO_PROP) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private Integer positiveOrZeroProp; + """, + """ + @Nullable + @Max(value = 0, message = "This is negative message") + @JsonProperty(JSON_PROPERTY_NEGATIVE_PROP) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private Integer negativeProp; + """, + """ + @Nullable + @Max(value = 0, message = "This is negative or zero message") + @JsonProperty(JSON_PROPERTY_NEGATIVE_OR_ZERO_PROP) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private Integer negativeOrZeroProp; + """, + """ + @Nullable + @DecimalMin(value = "5.5", message = "This is decimal min message") + @DecimalMax(value = "10.5", message = "This is decimal max message") + @JsonProperty(JSON_PROPERTY_DECIMAL_PROP) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private BigDecimal decimalProp; + """, + """ + @Nullable + @DecimalMin(value = "5.5", inclusive = false, message = "This is decimal min message") + @DecimalMax(value = "10.5", inclusive = false, message = "This is decimal max message") + @JsonProperty(JSON_PROPERTY_DECIMAL_PROP2) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private BigDecimal decimalProp2; + """, + """ + @Nullable + @Size(min = 5, max = 10, message = "This is min max string length message") + @JsonProperty(JSON_PROPERTY_ARRAY_PROP1) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private List<@NotNull Integer> arrayProp1; + """, + """ + @Nullable + @Size(min = 5, message = "This is min max string length message") + @JsonProperty(JSON_PROPERTY_ARRAY_PROP2) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private List<@NotNull Integer> arrayProp2; + """, + """ + @Nullable + @Size(max = 10, message = "This is min max string length message") + @JsonProperty(JSON_PROPERTY_ARRAY_PROP3) + @JsonInclude(JsonInclude.Include.USE_DEFAULTS) + private List<@NotNull Integer> arrayProp3; + """ + ); + } } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java index 99d91ca650..ea799ed223 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java @@ -593,4 +593,48 @@ public CurrencyInvoiceCreateDto sellerVatId(String sellerVatId) { """ ); } + + @Test + void testCustomValidationMessages() { + + var codegen = new JavaMicronautServerCodegen(); + codegen.setUseEnumCaseInsensitive(true); + String outputPath = generateFiles(codegen, "src/test/resources/3_0/validation-messages.yml", CodegenConstants.APIS, CodegenConstants.MODELS); + String path = outputPath + "src/main/java/org/openapitools/"; + + assertFileContains(path + "api/BooksApi.java", + """ + @QueryValue("emailParam") @NotNull List<@Email(regexp = "email@dot.com", message = "This is email pattern message") @Size(min = 5, max = 10, message = "This is min max email length message") @NotNull(message = "This is required email message") String> emailParam, + """, + """ + @QueryValue("strParam") @NotNull List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String> strParam, + """, + """ + @QueryValue("strParam2") @NotNull List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, message = "This is min max string length message") @NotNull(message = "This is required string message") String> strParam2, + """, + """ + @QueryValue("strParam3") @NotNull List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String> strParam3, + """, + """ + @QueryValue("intParam") @NotNull List<@NotNull(message = "This is required int message") @Min(value = 5, message = "This is min message") @Max(value = 10, message = "This is max message") Integer> intParam, + """, + """ + @QueryValue("decimalParam") @NotNull List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", message = "This is decimal min message") @DecimalMax(value = "10.5", message = "This is decimal max message") BigDecimal> decimalParam, + """, + """ + @QueryValue("decimalParam2") @NotNull(message = "This is required param message") List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", inclusive = false, message = "This is decimal min message") @DecimalMax(value = "10.5", inclusive = false, message = "This is decimal max message") BigDecimal> decimalParam2, + """, + """ + @QueryValue("positiveParam") @NotNull List<@NotNull(message = "This is required int message") @Positive(message = "This is positive message") Integer> positiveParam, + """, + """ + @QueryValue("positiveOrZeroParam") @NotNull List<@NotNull(message = "This is required int message") @PositiveOrZero(message = "This is positive or zero message") Integer> positiveOrZeroParam, + """, + """ + @QueryValue("negativeParam") @NotNull List<@NotNull(message = "This is required int message") @Negative(message = "This is negative message") Integer> negativeParam, + """, + """ + @QueryValue("negativeOrZeroParam") @NotNull List<@NotNull(message = "This is required int message") @NegativeOrZero(message = "This is negative or zero message") Integer> negativeOrZeroParam, + """); + } } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java index 70de70ab9a..9a366a1d0d 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java @@ -1042,4 +1042,152 @@ void testPrimitives() { "longTypes: List<@NotNull Long>" ); } + + @Test + void testCustomValidationMessages() { + + var codegen = new KotlinMicronautClientCodegen(); + String outputPath = generateFiles(codegen, "src/test/resources/3_0/validation-messages.yml", CodegenConstants.APIS, CodegenConstants.MODELS); + String path = outputPath + "src/main/kotlin/org/openapitools/"; + + assertFileContains(path + "api/BooksApi.kt", + """ + @QueryValue("emailParam") @NotNull emailParam: List<@Email(regexp = "email@dot.com", message = "This is email pattern message") @Size(min = 5, max = 10, message = "This is min max email length message") @NotNull(message = "This is required email message") String>, + """, + """ + @QueryValue("strParam") @NotNull strParam: List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String>, + """, + """ + @QueryValue("strParam2") @NotNull strParam2: List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, message = "This is min max string length message") @NotNull(message = "This is required string message") String>, + """, + """ + @QueryValue("strParam3") @NotNull strParam3: List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String>, + """, + """ + @QueryValue("intParam") @NotNull intParam: List<@NotNull(message = "This is required int message") @Min(value = 5, message = "This is min message") @Max(value = 10, message = "This is max message") Int>, + """, + """ + @QueryValue("decimalParam") @NotNull decimalParam: List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", message = "This is decimal min message") @DecimalMax(value = "10.5", message = "This is decimal max message") BigDecimal>, + """, + """ + @QueryValue("decimalParam2") @NotNull(message = "This is required param message") decimalParam2: List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", inclusive = false, message = "This is decimal min message") @DecimalMax(value = "10.5", inclusive = false, message = "This is decimal max message") BigDecimal>, + """, + """ + @QueryValue("positiveParam") @NotNull positiveParam: List<@NotNull(message = "This is required int message") @Positive(message = "This is positive message") Int>, + """, + """ + @QueryValue("positiveOrZeroParam") @NotNull positiveOrZeroParam: List<@NotNull(message = "This is required int message") @PositiveOrZero(message = "This is positive or zero message") Int>, + """, + """ + @QueryValue("negativeParam") @NotNull negativeParam: List<@NotNull(message = "This is required int message") @Negative(message = "This is negative message") Int>, + """, + """ + @QueryValue("negativeOrZeroParam") @NotNull negativeOrZeroParam: List<@NotNull(message = "This is required int message") @NegativeOrZero(message = "This is negative or zero message") Int>, + """); + + assertFileContains(path + "model/Book.kt", + """ + @field:NotNull(message = "This is required string message") + @field:Pattern(regexp = "[a-zA-Z ]+", message = "This is string pattern message") + @field:Size(min = 5, max = 10, message = "This is min max string length message") + @field:JsonProperty(JSON_PROPERTY_STR_PROP) + var strProp: String, + """, + """ + @field:NotNull(message = "This is required email message") + @field:Size(min = 5, max = 10, message = "This is min max email length message") + @field:Email(regexp = "email@dot.com", message = "This is email pattern message") + @field:JsonProperty(JSON_PROPERTY_EMAIL_PROP) + var emailProp: String, + """, + """ + @field:NotNull(message = "This is required int message") + @field:Min(value = 5, message = "This is min message") + @field:Max(value = 10, message = "This is max message") + @field:JsonProperty(JSON_PROPERTY_INT_PROP) + var intProp: Int, + """, + """ + @field:Nullable + @field:Pattern(regexp = "[a-zA-Z ]+", message = "This is string pattern message") + @field:Size(min = 5, message = "This is min string length message") + @field:JsonProperty(JSON_PROPERTY_STR_PROP2) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var strProp2: String? = null, + """, + """ + @field:Nullable + @field:Pattern(regexp = "[a-zA-Z ]+", message = "This is string pattern message") + @field:Size(max = 10, message = "This is min string length message") + @field:JsonProperty(JSON_PROPERTY_STR_PROP3) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var strProp3: String? = null, + """, + """ + @field:Nullable + @field:Min(value = 0, message = "This is positive message") + @field:JsonProperty(JSON_PROPERTY_POSITIVE_PROP) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var positiveProp: Int? = null, + """, + """ + @field:Nullable + @field:Min(value = 0, message = "This is positive or zero message") + @field:JsonProperty(JSON_PROPERTY_POSITIVE_OR_ZERO_PROP) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var positiveOrZeroProp: Int? = null, + """, + """ + @field:Nullable + @field:Max(value = 0, message = "This is negative message") + @field:JsonProperty(JSON_PROPERTY_NEGATIVE_PROP) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var negativeProp: Int? = null, + """, + """ + @field:Nullable + @field:Max(value = 0, message = "This is negative or zero message") + @field:JsonProperty(JSON_PROPERTY_NEGATIVE_OR_ZERO_PROP) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var negativeOrZeroProp: Int? = null, + """, + """ + @field:Nullable + @field:DecimalMin(value = "5.5", message = "This is decimal min message") + @field:DecimalMax(value = "10.5", message = "This is decimal max message") + @field:JsonProperty(JSON_PROPERTY_DECIMAL_PROP) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var decimalProp: BigDecimal? = null, + """, + """ + @field:Nullable + @field:DecimalMin(value = "5.5", inclusive = false, message = "This is decimal min message") + @field:DecimalMax(value = "10.5", inclusive = false, message = "This is decimal max message") + @field:JsonProperty(JSON_PROPERTY_DECIMAL_PROP2) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var decimalProp2: BigDecimal? = null, + """, + """ + @field:Nullable + @field:Size(min = 5, max = 10, message = "This is min max string length message") + @field:JsonProperty(JSON_PROPERTY_ARRAY_PROP1) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var arrayProp1: List<@NotNull Int>? = null, + """, + """ + @field:Nullable + @field:Size(min = 5, message = "This is min max string length message") + @field:JsonProperty(JSON_PROPERTY_ARRAY_PROP2) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var arrayProp2: List<@NotNull Int>? = null, + """, + """ + @field:Nullable + @field:Size(max = 10, message = "This is min max string length message") + @field:JsonProperty(JSON_PROPERTY_ARRAY_PROP3) + @field:JsonInclude(JsonInclude.Include.USE_DEFAULTS) + var arrayProp3: List<@NotNull Int>? = null, + """ + ); + } } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java index 98409f6d0f..f70397e03b 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java @@ -665,4 +665,47 @@ void testPolymorphism() { """ ); } + + @Test + void testCustomValidationMessages() { + + var codegen = new KotlinMicronautServerCodegen(); + String outputPath = generateFiles(codegen, "src/test/resources/3_0/validation-messages.yml", CodegenConstants.APIS, CodegenConstants.MODELS); + String path = outputPath + "src/main/kotlin/org/openapitools/"; + + assertFileContains(path + "api/BooksApi.kt", + """ + @QueryValue("emailParam") @NotNull emailParam: List<@Email(regexp = "email@dot.com", message = "This is email pattern message") @Size(min = 5, max = 10, message = "This is min max email length message") @NotNull(message = "This is required email message") String>, + """, + """ + @QueryValue("strParam") @NotNull strParam: List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String>, + """, + """ + @QueryValue("strParam2") @NotNull strParam2: List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(min = 5, message = "This is min max string length message") @NotNull(message = "This is required string message") String>, + """, + """ + @QueryValue("strParam3") @NotNull strParam3: List<@Pattern(regexp = "my_pattern", message = "This is string pattern message") @Size(max = 10, message = "This is min max string length message") @NotNull(message = "This is required string message") String>, + """, + """ + @QueryValue("intParam") @NotNull intParam: List<@NotNull(message = "This is required int message") @Min(value = 5, message = "This is min message") @Max(value = 10, message = "This is max message") Int>, + """, + """ + @QueryValue("decimalParam") @NotNull decimalParam: List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", message = "This is decimal min message") @DecimalMax(value = "10.5", message = "This is decimal max message") BigDecimal>, + """, + """ + @QueryValue("decimalParam2") @NotNull(message = "This is required param message") decimalParam2: List<@NotNull(message = "This is required decimal message") @DecimalMin(value = "5.5", inclusive = false, message = "This is decimal min message") @DecimalMax(value = "10.5", inclusive = false, message = "This is decimal max message") BigDecimal>, + """, + """ + @QueryValue("positiveParam") @NotNull positiveParam: List<@NotNull(message = "This is required int message") @Positive(message = "This is positive message") Int>, + """, + """ + @QueryValue("positiveOrZeroParam") @NotNull positiveOrZeroParam: List<@NotNull(message = "This is required int message") @PositiveOrZero(message = "This is positive or zero message") Int>, + """, + """ + @QueryValue("negativeParam") @NotNull negativeParam: List<@NotNull(message = "This is required int message") @Negative(message = "This is negative message") Int>, + """, + """ + @QueryValue("negativeOrZeroParam") @NotNull negativeOrZeroParam: List<@NotNull(message = "This is required int message") @NegativeOrZero(message = "This is negative or zero message") Int>, + """); + } } diff --git a/openapi-generator/src/test/resources/3_0/validation-messages.yml b/openapi-generator/src/test/resources/3_0/validation-messages.yml new file mode 100644 index 0000000000..2f2180ee47 --- /dev/null +++ b/openapi-generator/src/test/resources/3_0/validation-messages.yml @@ -0,0 +1,292 @@ +openapi: 3.0.0 +info: + description: This is a library API + version: 1.0.0 + title: Library + license: + name: Apache-2.0 + url: "https://www.apache.org/licenses/LICENSE-2.0.html" +tags: + - name: books + description: Add books +paths: + /add-book: + post: + tags: [books] + summary: Add a new book + operationId: addBook + parameters: + - name: emailParam + in: query + required: true + schema: + type: array + items: + type: string + format: email + pattern: email@dot.com + minLength: 5 + maxLength: 10 + x-pattern-message: This is email pattern message + x-size-message: This is min max email length message + x-not-null-message: This is required email message + + - name: strParam + in: query + required: true + schema: + type: array + items: + type: string + pattern: my_pattern + minLength: 5 + maxLength: 10 + x-pattern-message: This is string pattern message + x-size-message: This is min max string length message + x-not-null-message: This is required string message + - name: strParam2 + in: query + required: true + schema: + type: array + items: + type: string + pattern: my_pattern + minLength: 5 + x-pattern-message: This is string pattern message + x-size-message: This is min max string length message + x-not-null-message: This is required string message + + - name: strParam3 + in: query + required: true + schema: + type: array + items: + type: string + pattern: my_pattern + maxLength: 10 + x-pattern-message: This is string pattern message + x-size-message: This is min max string length message + x-not-null-message: This is required string message + + - name: intParam + in: query + required: true + schema: + type: array + items: + type: integer + format: int32 + minimum: 5 + maximum: 10 + x-min-message: This is min message + x-max-message: This is max message + x-not-null-message: This is required int message + + - name: decimalParam + in: query + required: true + schema: + type: array + items: + type: number + minimum: 5.5 + maximum: 10.5 + x-min-message: This is decimal min message + x-max-message: This is decimal max message + x-not-null-message: This is required decimal message + + - name: decimalParam2 + in: query + required: true + schema: + type: array + items: + type: number + minimum: 5.5 + exclusiveMinimum: true + maximum: 10.5 + exclusiveMaximum: true + x-min-message: This is decimal min message + x-max-message: This is decimal max message + x-not-null-message: This is required decimal message + x-not-null-message: This is required param message + + - name: positiveParam + in: query + required: true + schema: + type: array + items: + type: integer + format: int32 + minimum: 0 + exclusiveMinimum: true + x-min-message: This is positive message + x-not-null-message: This is required int message + + - name: positiveOrZeroParam + in: query + required: true + schema: + type: array + items: + type: integer + format: int32 + minimum: 0 + exclusiveMinimum: false + x-min-message: This is positive or zero message + x-not-null-message: This is required int message + + - name: negativeParam + in: query + required: true + schema: + type: array + items: + type: integer + format: int32 + maximum: 0 + exclusiveMaximum: true + x-max-message: This is negative message + x-not-null-message: This is required int message + + - name: negativeOrZeroParam + in: query + required: true + schema: + type: array + items: + type: integer + format: int32 + maximum: 0 + exclusiveMaximum: false + x-max-message: This is negative or zero message + x-not-null-message: This is required int message + + requestBody: + required: true + content: + "application/json": + schema: + $ref: "#/components/schemas/Book" + responses: + "200": + description: Success + "400": + description: Bad Request +components: + schemas: + Book: + type: object + required: + - strProp + - intProp + - emailProp + properties: + strProp: + type: string + minLength: 5 + maxLength: 10 + pattern: "[a-zA-Z ]+" + x-pattern-message: This is string pattern message + x-size-message: This is min max string length message + x-not-null-message: This is required string message + strProp2: + type: string + minLength: 5 + pattern: "[a-zA-Z ]+" + x-pattern-message: This is string pattern message + x-size-message: This is min string length message + x-not-null-message: This is required string message + strProp3: + type: string + maxLength: 10 + pattern: "[a-zA-Z ]+" + x-pattern-message: This is string pattern message + x-size-message: This is min string length message + x-not-null-message: This is required string message + emailProp: + type: string + format: email + pattern: email@dot.com + minLength: 5 + maxLength: 10 + x-pattern-message: This is email pattern message + x-size-message: This is min max email length message + x-not-null-message: This is required email message + intProp: + type: integer + format: int32 + minimum: 5 + maximum: 10 + x-min-message: This is min message + x-max-message: This is max message + x-not-null-message: This is required int message + positiveProp: + type: integer + format: int32 + minimum: 0 + exclusiveMinimum: true + x-min-message: This is positive message + x-not-null-message: This is required int message + positiveOrZeroProp: + type: integer + format: int32 + minimum: 0 + exclusiveMinimum: false + x-min-message: This is positive or zero message + x-not-null-message: This is required int message + negativeProp: + type: integer + format: int32 + maximum: 0 + exclusiveMaximum: true + x-max-message: This is negative message + x-not-null-message: This is required int message + negativeOrZeroProp: + type: integer + format: int32 + maximum: 0 + exclusiveMaximum: false + x-max-message: This is negative or zero message + x-not-null-message: This is required int message + decimalProp: + type: number + minimum: 5.5 + maximum: 10.5 + x-min-message: This is decimal min message + x-max-message: This is decimal max message + x-not-null-message: This is required decimal message + decimalProp2: + type: number + minimum: 5.5 + exclusiveMinimum: true + maximum: 10.5 + exclusiveMaximum: true + x-min-message: This is decimal min message + x-max-message: This is decimal max message + x-not-null-message: This is required decimal message + arrayProp1: + type: array + items: + type: integer + minItems: 5 + maxItems: 10 + x-size-message: This is min max string length message + x-not-null-message: This is required string message + arrayProp2: + type: array + items: + type: integer + minItems: 5 + x-size-message: This is min max string length message + x-not-null-message: This is required string message + arrayProp3: + type: array + items: + type: integer + maxItems: 10 + x-size-message: This is min max string length message + x-not-null-message: This is required string message