From 83a1ca174803271099e67b0d0d9ea344c1cc1e01 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Wed, 24 Jan 2024 14:32:24 +0100 Subject: [PATCH 01/13] Add explode attribute to header annotation --- .../v3/core/util/AnnotationsUtils.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index 9e9af0ab83..93ec50c75d 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -10,6 +10,7 @@ import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.oas.annotations.StringToClassMapItem; +import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.links.LinkParameter; @@ -33,6 +34,7 @@ import io.swagger.v3.oas.models.media.JsonSchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.servers.ServerVariable; import io.swagger.v3.oas.models.servers.ServerVariables; @@ -1335,6 +1337,7 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H isEmpty = false; } headerObject.setStyle(Header.StyleEnum.SIMPLE); + setHeaderExplode(headerObject, header); if (header.schema() != null) { if (header.schema().implementation().equals(Void.class)) { @@ -1350,6 +1353,30 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H return Optional.of(headerObject); } + public static void setHeaderExplode (Header header, io.swagger.v3.oas.annotations.headers.Header h) { + if (isExplodable(h, header)) { + if (Explode.TRUE.equals(h.explode())) { + header.setExplode(Boolean.TRUE); + } else if (Explode.FALSE.equals(h.explode())) { + header.setExplode(Boolean.FALSE); + } + } + } + + private static boolean isExplodable(io.swagger.v3.oas.annotations.headers.Header h, Header header) { + io.swagger.v3.oas.annotations.media.Schema schema = h.schema(); + boolean explode = true; + if (schema != null) { + Class implementation = schema.implementation(); + if (implementation == Void.class) { + if (!schema.type().equals("object") && !schema.type().equals("array")) { + explode = false; + } + } + } + return explode; + } + public static void addEncodingToMediaType(MediaType mediaType, io.swagger.v3.oas.annotations.media.Encoding encoding, JsonView jsonViewAnnotation) { addEncodingToMediaType(mediaType, encoding, jsonViewAnnotation, false); } From 363d4bc05ac7af352b1ccbb7f544bece4f3cc5ad Mon Sep 17 00:00:00 2001 From: MicRyc Date: Fri, 26 Jan 2024 07:51:00 +0100 Subject: [PATCH 02/13] Add hidden attribute --- .../src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index 93ec50c75d..a3a2132477 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1315,7 +1315,7 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation, boolean openapi31) { - if (header == null) { + if (header == null || header.hidden()) { return Optional.empty(); } From 55b2f730a2d7ea860e2f5fb2d881572eeea1d681 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Fri, 26 Jan 2024 08:29:05 +0100 Subject: [PATCH 03/13] Add example,examples attributes --- .../v3/core/util/AnnotationsUtils.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index a3a2132477..c27a8f48ba 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1329,6 +1329,13 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H headerObject.set$ref(header.ref()); isEmpty = false; } + if (StringUtils.isNotBlank(header.example())) { + try { + headerObject.setExample(Json.mapper().readTree(header.example())); + } catch (IOException e) { + headerObject.setExample(header.example()); + } + } if (header.deprecated()) { headerObject.setDeprecated(header.deprecated()); } @@ -1336,6 +1343,18 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H headerObject.setRequired(header.required()); isEmpty = false; } + Map exampleMap = new LinkedHashMap<>(); + if (header.examples().length == 1 && StringUtils.isBlank(header.examples()[0].name())) { + Optional exampleOptional = AnnotationsUtils.getExample(header.examples()[0], true); + exampleOptional.ifPresent(headerObject::setExample); + } else { + for (ExampleObject exampleObject : header.examples()) { + AnnotationsUtils.getExample(exampleObject).ifPresent(example -> exampleMap.put(exampleObject.name(), example)); + } + } + if (!exampleMap.isEmpty()) { + headerObject.setExamples(exampleMap); + } headerObject.setStyle(Header.StyleEnum.SIMPLE); setHeaderExplode(headerObject, header); From de2ad480a2a9ec828d1e750579373b34ebbd003e Mon Sep 17 00:00:00 2001 From: MicRyc Date: Fri, 26 Jan 2024 11:10:51 +0100 Subject: [PATCH 04/13] Add array attribute --- .../main/java/io/swagger/v3/core/util/AnnotationsUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index c27a8f48ba..f7febffe21 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1364,6 +1364,10 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H headerObject::setSchema); } } + if (hasArrayAnnotation(header.array())){ + AnnotationsUtils.getArraySchema(header.array(), null, jsonViewAnnotation, openapi31).ifPresent( + headerObject::setSchema); + } if (isEmpty) { return Optional.empty(); From 3ba1cc869775acce818d8aa3af9ab405f795ace0 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Mon, 29 Jan 2024 10:53:49 +0100 Subject: [PATCH 05/13] Add explode,hidden,example and examples attributes tests --- .../main/java/io/swagger/v3/core/util/AnnotationsUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index f7febffe21..58306bf111 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1356,7 +1356,6 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H headerObject.setExamples(exampleMap); } headerObject.setStyle(Header.StyleEnum.SIMPLE); - setHeaderExplode(headerObject, header); if (header.schema() != null) { if (header.schema().implementation().equals(Void.class)) { @@ -1369,6 +1368,7 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H headerObject::setSchema); } + setHeaderExplode(headerObject, header); if (isEmpty) { return Optional.empty(); } @@ -1377,7 +1377,7 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H } public static void setHeaderExplode (Header header, io.swagger.v3.oas.annotations.headers.Header h) { - if (isExplodable(h, header)) { + if (isHeaderExplodable(h, header)) { if (Explode.TRUE.equals(h.explode())) { header.setExplode(Boolean.TRUE); } else if (Explode.FALSE.equals(h.explode())) { @@ -1386,7 +1386,7 @@ public static void setHeaderExplode (Header header, io.swagger.v3.oas.annotation } } - private static boolean isExplodable(io.swagger.v3.oas.annotations.headers.Header h, Header header) { + private static boolean isHeaderExplodable(io.swagger.v3.oas.annotations.headers.Header h, Header header) { io.swagger.v3.oas.annotations.media.Schema schema = h.schema(); boolean explode = true; if (schema != null) { From 129196f4bf56306e5bb3f3a4176e2d8b52269e13 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Mon, 29 Jan 2024 11:37:57 +0100 Subject: [PATCH 06/13] Add Header with ArraySchema attribute test --- .../v3/oas/annotations/headers/Header.java | 39 ++++ .../AnnotatedOperationMethodTest.java | 218 ++++++++++++++++++ 2 files changed, 257 insertions(+) diff --git a/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/headers/Header.java b/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/headers/Header.java index f4562ad2f8..b9bc2031c3 100644 --- a/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/headers/Header.java +++ b/modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/headers/Header.java @@ -1,5 +1,8 @@ package io.swagger.v3.oas.annotations.headers; +import io.swagger.v3.oas.annotations.enums.Explode; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import java.lang.annotation.Inherited; @@ -64,4 +67,40 @@ **/ String ref() default ""; + + /** + * When this is true, parameter values of type array or object generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters this property has no effect. When style is form, the default value is true. For all other styles, the default value is false. Ignored if the properties content or array are specified. + * + * @return whether or not to expand individual array members + **/ + Explode explode() default Explode.DEFAULT; + + /** + * Allows this header to be marked as hidden + * + * @return whether or not this header is hidden + */ + boolean hidden() default false; + + /** + * Provides an example of the schema. When associated with a specific media type, the example string shall be parsed by the consumer to be treated as an object or an array. Ignored if the properties examples, content or array are specified. + * + * @return an example of the header + **/ + String example() default ""; + + /** + * An array of examples of the schema used to show the use of the associated schema. + * + * @return array of examples of the header + **/ + ExampleObject[] examples() default {}; + + /** + * The schema of the array that defines this header. Ignored if the property content is specified. + * + * @return the schema of the array + */ + ArraySchema array() default @ArraySchema(); + } diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java index 6d9f4aede4..c9f2ac58e0 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java @@ -1,6 +1,7 @@ package io.swagger.v3.jaxrs2.annotations.operations; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; +import io.swagger.v3.jaxrs2.petstore31.User; import io.swagger.v3.jaxrs2.resources.GenericResponsesResource; import io.swagger.v3.jaxrs2.resources.HiddenAnnotatedUserResource; import io.swagger.v3.jaxrs2.resources.HiddenUserResource; @@ -10,8 +11,10 @@ import io.swagger.v3.jaxrs2.resources.UserResource; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; @@ -359,6 +362,140 @@ static class GetOperationWithResponseMultipleHeaders { public void simpleGet() { } } + @Test + public void testOperationWithResponseArraySchema() { + String openApiYAML = readIntoYaml(GetOperationResponseHeaderWithArraySchema.class); + int start = openApiYAML.indexOf("get:"); + String extractedYAML = openApiYAML.substring(start); + String expectedYAML = "get:\n" + + " summary: Simple get operation\n" + + " description: Defines a simple get operation with no inputs and a complex output\n" + + " operationId: getWithPayloadResponse\n" + + " responses:\n" + + " \"200\":\n" + + " description: voila!\n" + + " headers:\n" + + " Rate-Limit-Limit:\n" + + " description: The number of allowed requests in the current period\n" + + " style: simple\n" + + " schema:\n" + + " maxItems: 10\n" + + " minItems: 1\n" + + " type: array\n" + + " items:\n" + + " type: integer\n" + + " deprecated: true\n"; + System.out.println(extractedYAML); + assertEquals(expectedYAML, extractedYAML); + } + static class GetOperationResponseHeaderWithArraySchema { + @Operation( + summary = "Simple get operation", + description = "Defines a simple get operation with no inputs and a complex output", + operationId = "getWithPayloadResponse", + deprecated = true, + responses = { + @ApiResponse( + responseCode = "200", + description = "voila!", + headers = {@Header( + name = "Rate-Limit-Limit", + description = "The number of allowed requests in the current period", + array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(type = "integer")))})}) + @GET + @Path("/path") + public void simpleGet() { + } + } + static class GetOperationResponseWithoutHiddenHeader { + @Operation( + summary = "Simple get operation", + description = "Defines a simple get operation with no inputs and a complex output", + operationId = "getWithPayloadResponse", + deprecated = true, + responses = { + @ApiResponse( + responseCode = "200", + description = "voila!", + headers = {@Header( + hidden = true, + name = "Rate-Limit-Limit", + description = "The number of allowed requests in the current period", + schema = @Schema(type = "integer")), + @Header( + name = "X-Rate-Limit-Desc", + description = "The description of rate limit", + schema = @Schema(type = "string"))}) + }) + @GET + @Path("/path") + public void simpleGet() { + } + } + static class GetOperationWithResponseMultipleHeadersAndExamples { + @Operation( + summary = "Simple get operation", + description = "Defines a simple get operation with no inputs and a complex output", + operationId = "getWithPayloadResponse", + deprecated = true, + responses = { + @ApiResponse( + responseCode = "200", + description = "voila!", + headers = {@Header( + examples = { + @ExampleObject( + name = "ex 1", + description = "example description", + value = "example value" + ), + @ExampleObject( + name = "ex 2", + description = "example description 2", + value = "example value 2" + ) + }, + name = "Rate-Limit-Limit", + description = "The number of allowed requests in the current period", + schema = @Schema(type = "object")), + @Header( + name = "X-Rate-Limit-Desc", + description = "The description of rate limit", + array = @ArraySchema(schema = @Schema()), + example = "example1")}) + + }) + @GET + @Path("/path") + public void simpleGet() { + } + } + static class GetOperationResponseWithHeaderExplodeAttribute { + @Operation( + summary = "Simple get operation", + description = "Defines a simple get operation with no inputs and a complex output", + operationId = "getWithPayloadResponse", + deprecated = true, + responses = { + @ApiResponse( + responseCode = "200", + description = "voila!", + headers = {@Header( + name = "Rate-Limit-Limit", + description = "The number of allowed requests in the current period", + explode = Explode.TRUE, + schema = @Schema(type = "object")), + @Header( + name = "X-Rate-Limit-Desc", + description = "The description of rate limit", + explode = Explode.FALSE, + schema = @Schema(type = "array"))}) + }) + @GET + @Path("/path") + public void simpleGet() { + } + } @Test public void testOperationWithResponseMultipleHeaders() { @@ -386,6 +523,87 @@ public void testOperationWithResponseMultipleHeaders() { " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } + @Test + public void testOperationWithResponseMultipleHeadersAndExplodeAttribute() { + String openApiYAML = readIntoYaml(GetOperationResponseWithHeaderExplodeAttribute.class); + int start = openApiYAML.indexOf("get:"); + String extractedYAML = openApiYAML.substring(start); + String expectedYAML = "get:\n" + + " summary: Simple get operation\n" + + " description: Defines a simple get operation with no inputs and a complex output\n" + + " operationId: getWithPayloadResponse\n" + + " responses:\n" + + " \"200\":\n" + + " description: voila!\n" + + " headers:\n" + + " X-Rate-Limit-Desc:\n" + + " description: The description of rate limit\n" + + " style: simple\n" + + " explode: false\n" + + " schema:\n" + + " type: array\n" + + " Rate-Limit-Limit:\n" + + " description: The number of allowed requests in the current period\n" + + " style: simple\n" + + " explode: true\n" + + " schema:\n" + + " type: object\n" + + " deprecated: true\n"; + assertEquals(expectedYAML, extractedYAML); + } + @Test + public void testOperationResponseWithoutHiddenHeader() { + String openApiYAML = readIntoYaml(GetOperationResponseWithoutHiddenHeader.class); + int start = openApiYAML.indexOf("get:"); + String extractedYAML = openApiYAML.substring(start); + String expectedYAML = "get:\n" + + " summary: Simple get operation\n" + + " description: Defines a simple get operation with no inputs and a complex output\n" + + " operationId: getWithPayloadResponse\n" + + " responses:\n" + + " \"200\":\n" + + " description: voila!\n" + + " headers:\n" + + " X-Rate-Limit-Desc:\n" + + " description: The description of rate limit\n" + + " style: simple\n" + + " schema:\n" + + " type: string\n" + + " deprecated: true\n"; + assertEquals(expectedYAML, extractedYAML); + } + @Test + public void testOperationWithResponseMultipleHeadersAndExamples() { + String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersAndExamples.class); + int start = openApiYAML.indexOf("get:"); + String extractedYAML = openApiYAML.substring(start); + String expectedYAML = "get:\n" + + " summary: Simple get operation\n" + + " description: Defines a simple get operation with no inputs and a complex output\n" + + " operationId: getWithPayloadResponse\n" + + " responses:\n" + + " \"200\":\n" + + " description: voila!\n" + + " headers:\n" + + " X-Rate-Limit-Desc:\n" + + " description: The description of rate limit\n" + + " style: simple\n" + + " example: example1\n" + + " Rate-Limit-Limit:\n" + + " description: The number of allowed requests in the current period\n" + + " style: simple\n" + + " schema:\n" + + " type: object\n" + + " examples:\n" + + " ex 1:\n" + + " description: example description\n" + + " value: example value\n" + + " ex 2:\n" + + " description: example description 2\n" + + " value: example value 2\n" + + " deprecated: true\n"; + assertEquals(expectedYAML, extractedYAML); + } @Test(description = "reads the pet resource from sample") public void testCompletePetResource() throws IOException { From 6ded4862adbbe34986a350945f1c8bf34b7a9a14 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Mon, 29 Jan 2024 11:48:00 +0100 Subject: [PATCH 07/13] Delete sout in test --- .../annotations/operations/AnnotatedOperationMethodTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java index c9f2ac58e0..3a638188d4 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java @@ -385,7 +385,6 @@ public void testOperationWithResponseArraySchema() { " items:\n" + " type: integer\n" + " deprecated: true\n"; - System.out.println(extractedYAML); assertEquals(expectedYAML, extractedYAML); } static class GetOperationResponseHeaderWithArraySchema { From 5aae5258e7afb9b3277e9689a0e9e87ef1e3386f Mon Sep 17 00:00:00 2001 From: MicRyc Date: Wed, 31 Jan 2024 09:43:35 +0100 Subject: [PATCH 08/13] Fix schema implementation parsing process --- .../v3/core/util/AnnotationsUtils.java | 32 ++++++--- .../AnnotationsUtilsHeadersTest.java | 2 +- .../io/swagger/v3/jaxrs2/OperationParser.java | 2 +- .../AnnotatedOperationMethodTest.java | 71 +++++++++++++++++++ 4 files changed, 96 insertions(+), 11 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index 58306bf111..d959c5ec44 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1289,18 +1289,18 @@ public static Map getLinkParameters(LinkParameter[] linkParamete return linkParametersMap; } - public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, JsonView jsonViewAnnotation) { - return getHeaders(annotationHeaders, jsonViewAnnotation, false); + public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, Components components, JsonView jsonViewAnnotation) { + return getHeaders(annotationHeaders, components, jsonViewAnnotation, false); } - public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, JsonView jsonViewAnnotation, boolean openapi31) { + public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (annotationHeaders == null) { return Optional.empty(); } Map headers = new HashMap<>(); for (io.swagger.v3.oas.annotations.headers.Header header : annotationHeaders) { - getHeader(header, jsonViewAnnotation).ifPresent(headerResult -> headers.put(header.name(), headerResult)); + getHeader(header, components, jsonViewAnnotation).ifPresent(headerResult -> headers.put(header.name(), headerResult)); } if (headers.size() == 0) { @@ -1309,11 +1309,11 @@ public static Optional> getHeaders(io.swagger.v3.oas.annotat return Optional.of(headers); } - public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation) { - return getHeader(header, jsonViewAnnotation, false); + public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, Components components, JsonView jsonViewAnnotation) { + return getHeader(header, components, jsonViewAnnotation, false); } - public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation, boolean openapi31) { + public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (header == null || header.hidden()) { return Optional.empty(); @@ -1361,10 +1361,24 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H if (header.schema().implementation().equals(Void.class)) { AnnotationsUtils.getSchemaFromAnnotation(header.schema(), jsonViewAnnotation, openapi31).ifPresent( headerObject::setSchema); + }else { + AnnotatedType annotatedType = new AnnotatedType() + .type(getSchemaType(header.schema())) + .resolveAsRef(true) + .skipOverride(true) + .jsonViewAnnotation(jsonViewAnnotation); + + + final ResolvedSchema resolvedSchema = ModelConverters.getInstance(openapi31).resolveAsResolvedSchema(annotatedType); + + if (resolvedSchema.schema != null) { + headerObject.setSchema(resolvedSchema.schema); + } + resolvedSchema.referencedSchemas.forEach(components::addSchemas); } } if (hasArrayAnnotation(header.array())){ - AnnotationsUtils.getArraySchema(header.array(), null, jsonViewAnnotation, openapi31).ifPresent( + AnnotationsUtils.getArraySchema(header.array(), components, jsonViewAnnotation, openapi31,null, true).ifPresent( headerObject::setSchema); } @@ -1426,7 +1440,7 @@ public static void addEncodingToMediaType(MediaType mediaType, io.swagger.v3.oas } if (encoding.headers() != null) { - getHeaders(encoding.headers(), jsonViewAnnotation, openapi31).ifPresent(encodingObject::headers); + getHeaders(encoding.headers(), null, jsonViewAnnotation, openapi31).ifPresent(encodingObject::headers); } if (encoding.extensions() != null && encoding.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, encoding.extensions()); diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java index a080ddb408..9cd2e41f82 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java @@ -46,7 +46,7 @@ public void extensionsTest(String methodName, .flatMap(response -> Arrays.stream(response.headers())).toArray(Header[]::new); final Optional> optionalMap = - AnnotationsUtils.getHeaders(headers, null); + AnnotationsUtils.getHeaders(headers,null, null); Assert.assertEquals(optionalMap, expected); } diff --git a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/OperationParser.java b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/OperationParser.java index b3f803e62f..599d1cd49d 100644 --- a/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/OperationParser.java +++ b/modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/OperationParser.java @@ -93,7 +93,7 @@ public static Optional getApiResponses(final io.swagger.v3.oas.ann AnnotationsUtils.getContent(response.content(), classProduces == null ? new String[0] : classProduces.value(), methodProduces == null ? new String[0] : methodProduces.value(), null, components, jsonViewAnnotation, openapi31).ifPresent(apiResponseObject::content); - AnnotationsUtils.getHeaders(response.headers(), jsonViewAnnotation).ifPresent(apiResponseObject::headers); + AnnotationsUtils.getHeaders(response.headers(), components, jsonViewAnnotation).ifPresent(apiResponseObject::headers); if (StringUtils.isNotBlank(apiResponseObject.getDescription()) || apiResponseObject.getContent() != null || apiResponseObject.getHeaders() != null) { Map links = AnnotationsUtils.getLinks(response.links()); diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java index 3a638188d4..a719b42c12 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java @@ -173,6 +173,9 @@ static class SampleResponseSchema { @Schema(description = "the user id") public String id; } + static class SampleHeaderSchema { + public String id; + } static class GenericError { public int code; @@ -349,6 +352,7 @@ static class GetOperationWithResponseMultipleHeaders { responseCode = "200", description = "voila!", headers = {@Header( + explode = Explode.TRUE, name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", schema = @Schema(type = "integer")), @@ -362,6 +366,7 @@ static class GetOperationWithResponseMultipleHeaders { public void simpleGet() { } } + @Test public void testOperationWithResponseArraySchema() { String openApiYAML = readIntoYaml(GetOperationResponseHeaderWithArraySchema.class); @@ -522,6 +527,72 @@ public void testOperationWithResponseMultipleHeaders() { " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } + static class GetOperationWithResponseMultipleHeadersWithImplementationSchema { + @Operation( + summary = "Simple get operation", + description = "Defines a simple get operation with no inputs and a complex output", + operationId = "getWithPayloadResponse", + deprecated = true, + responses = { + @ApiResponse( + responseCode = "200", + description = "voila!", + headers = {@Header( + explode = Explode.TRUE, + name = "Rate-Limit-Limit", + description = "The number of allowed requests in the current period", + array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(implementation = SampleHeaderSchema.class))), + @Header( + explode = Explode.TRUE, + name = "X-Rate-Limit-Desc", + description = "The description of rate limit", + schema = @Schema(type = "integer"))})}) + + + + @GET + @Path("/path") + public void simpleGet() { + } + } + @Test + public void testOperationWithResponseMultipleHeadersImplementationSchema() { + String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersWithImplementationSchema.class); + int start = openApiYAML.indexOf("get:"); + String extractedYAML = openApiYAML.substring(start); + String expectedYAML = "get:\n" + + " summary: Simple get operation\n" + + " description: Defines a simple get operation with no inputs and a complex output\n" + + " operationId: getWithPayloadResponse\n" + + " responses:\n" + + " \"200\":\n" + + " description: voila!\n" + + " headers:\n" + + " X-Rate-Limit-Desc:\n" + + " description: The description of rate limit\n" + + " style: simple\n" + + " schema:\n" + + " type: integer\n" + + " Rate-Limit-Limit:\n" + + " description: The number of allowed requests in the current period\n" + + " style: simple\n" + + " schema:\n" + + " maxItems: 10\n" + + " minItems: 1\n" + + " type: array\n" + + " items:\n" + + " $ref: '#/components/schemas/SampleHeaderSchema'\n" + + " deprecated: true\n" + + "components:\n" + + " schemas:\n" + + " SampleHeaderSchema:\n" + + " type: object\n" + + " properties:\n" + + " id:\n" + + " type: string\n"; + System.out.println(extractedYAML); + assertEquals(expectedYAML, extractedYAML); + } @Test public void testOperationWithResponseMultipleHeadersAndExplodeAttribute() { String openApiYAML = readIntoYaml(GetOperationResponseWithHeaderExplodeAttribute.class); From 6f884ae381507f5c55e04c9e5ec551c8098a5beb Mon Sep 17 00:00:00 2001 From: MicRyc Date: Wed, 31 Jan 2024 15:34:29 +0100 Subject: [PATCH 09/13] Delete unused imports and spaces --- .../io/swagger/v3/core/util/AnnotationsUtils.java | 3 --- .../operations/AnnotatedOperationMethodTest.java | 14 ++++++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index d959c5ec44..03aceb9803 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -34,7 +34,6 @@ import io.swagger.v3.oas.models.media.JsonSchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.servers.ServerVariable; import io.swagger.v3.oas.models.servers.ServerVariables; @@ -43,7 +42,6 @@ import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Field; @@ -1368,7 +1366,6 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H .skipOverride(true) .jsonViewAnnotation(jsonViewAnnotation); - final ResolvedSchema resolvedSchema = ModelConverters.getInstance(openapi31).resolveAsResolvedSchema(annotatedType); if (resolvedSchema.schema != null) { diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java index a719b42c12..919b350564 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java @@ -1,7 +1,6 @@ package io.swagger.v3.jaxrs2.annotations.operations; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; -import io.swagger.v3.jaxrs2.petstore31.User; import io.swagger.v3.jaxrs2.resources.GenericResponsesResource; import io.swagger.v3.jaxrs2.resources.HiddenAnnotatedUserResource; import io.swagger.v3.jaxrs2.resources.HiddenUserResource; @@ -21,7 +20,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import org.testng.annotations.Test; - import javax.ws.rs.GET; import javax.ws.rs.Path; import java.io.IOException; @@ -173,6 +171,7 @@ static class SampleResponseSchema { @Schema(description = "the user id") public String id; } + static class SampleHeaderSchema { public String id; } @@ -392,6 +391,7 @@ public void testOperationWithResponseArraySchema() { " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } + static class GetOperationResponseHeaderWithArraySchema { @Operation( summary = "Simple get operation", @@ -411,6 +411,7 @@ static class GetOperationResponseHeaderWithArraySchema { public void simpleGet() { } } + static class GetOperationResponseWithoutHiddenHeader { @Operation( summary = "Simple get operation", @@ -436,6 +437,7 @@ static class GetOperationResponseWithoutHiddenHeader { public void simpleGet() { } } + static class GetOperationWithResponseMultipleHeadersAndExamples { @Operation( summary = "Simple get operation", @@ -474,6 +476,7 @@ static class GetOperationWithResponseMultipleHeadersAndExamples { public void simpleGet() { } } + static class GetOperationResponseWithHeaderExplodeAttribute { @Operation( summary = "Simple get operation", @@ -527,6 +530,7 @@ public void testOperationWithResponseMultipleHeaders() { " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } + static class GetOperationWithResponseMultipleHeadersWithImplementationSchema { @Operation( summary = "Simple get operation", @@ -543,7 +547,6 @@ static class GetOperationWithResponseMultipleHeadersWithImplementationSchema { description = "The number of allowed requests in the current period", array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(implementation = SampleHeaderSchema.class))), @Header( - explode = Explode.TRUE, name = "X-Rate-Limit-Desc", description = "The description of rate limit", schema = @Schema(type = "integer"))})}) @@ -555,6 +558,7 @@ static class GetOperationWithResponseMultipleHeadersWithImplementationSchema { public void simpleGet() { } } + @Test public void testOperationWithResponseMultipleHeadersImplementationSchema() { String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersWithImplementationSchema.class); @@ -590,9 +594,9 @@ public void testOperationWithResponseMultipleHeadersImplementationSchema() { " properties:\n" + " id:\n" + " type: string\n"; - System.out.println(extractedYAML); assertEquals(expectedYAML, extractedYAML); } + @Test public void testOperationWithResponseMultipleHeadersAndExplodeAttribute() { String openApiYAML = readIntoYaml(GetOperationResponseWithHeaderExplodeAttribute.class); @@ -621,6 +625,7 @@ public void testOperationWithResponseMultipleHeadersAndExplodeAttribute() { " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } + @Test public void testOperationResponseWithoutHiddenHeader() { String openApiYAML = readIntoYaml(GetOperationResponseWithoutHiddenHeader.class); @@ -642,6 +647,7 @@ public void testOperationResponseWithoutHiddenHeader() { " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } + @Test public void testOperationWithResponseMultipleHeadersAndExamples() { String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersAndExamples.class); From a56905bc2a668be8c54d96bf6fdc1f8ba8d7a977 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Thu, 1 Feb 2024 10:07:04 +0100 Subject: [PATCH 10/13] Fix schema implementation test --- .../operations/AnnotatedOperationMethodTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java index 919b350564..b2ed91a39d 100644 --- a/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java +++ b/modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java @@ -547,9 +547,10 @@ static class GetOperationWithResponseMultipleHeadersWithImplementationSchema { description = "The number of allowed requests in the current period", array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(implementation = SampleHeaderSchema.class))), @Header( + explode = Explode.TRUE, name = "X-Rate-Limit-Desc", description = "The description of rate limit", - schema = @Schema(type = "integer"))})}) + schema = @Schema(implementation = SampleHeaderSchema.class))})}) @@ -575,8 +576,9 @@ public void testOperationWithResponseMultipleHeadersImplementationSchema() { " X-Rate-Limit-Desc:\n" + " description: The description of rate limit\n" + " style: simple\n" + + " explode: true\n" + " schema:\n" + - " type: integer\n" + + " $ref: '#/components/schemas/SampleHeaderSchema'\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " style: simple\n" + From 3cc802b75a7cab34824ab884303cec5b6c626c25 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Thu, 1 Feb 2024 12:00:42 +0100 Subject: [PATCH 11/13] Fix APIs backward compatibility --- .../java/io/swagger/v3/core/util/AnnotationsUtils.java | 10 ++++++++-- .../v3/core/resolving/AnnotationsUtilsHeadersTest.java | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index 03aceb9803..566e94af13 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1287,6 +1287,9 @@ public static Map getLinkParameters(LinkParameter[] linkParamete return linkParametersMap; } + public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, JsonView jsonViewAnnotation) { + return getHeaders(annotationHeaders, null, jsonViewAnnotation); + } public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, Components components, JsonView jsonViewAnnotation) { return getHeaders(annotationHeaders, components, jsonViewAnnotation, false); } @@ -1298,7 +1301,7 @@ public static Optional> getHeaders(io.swagger.v3.oas.annotat Map headers = new HashMap<>(); for (io.swagger.v3.oas.annotations.headers.Header header : annotationHeaders) { - getHeader(header, components, jsonViewAnnotation).ifPresent(headerResult -> headers.put(header.name(), headerResult)); + getHeader(header, components, jsonViewAnnotation, openapi31).ifPresent(headerResult -> headers.put(header.name(), headerResult)); } if (headers.size() == 0) { @@ -1307,6 +1310,9 @@ public static Optional> getHeaders(io.swagger.v3.oas.annotat return Optional.of(headers); } + public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation) { + return getHeader(header,null, jsonViewAnnotation); + } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, Components components, JsonView jsonViewAnnotation) { return getHeader(header, components, jsonViewAnnotation, false); } @@ -1375,7 +1381,7 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H } } if (hasArrayAnnotation(header.array())){ - AnnotationsUtils.getArraySchema(header.array(), components, jsonViewAnnotation, openapi31,null, true).ifPresent( + AnnotationsUtils.getArraySchema(header.array(), components, jsonViewAnnotation, openapi31, null, true).ifPresent( headerObject::setSchema); } diff --git a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java index 9cd2e41f82..26065877d4 100644 --- a/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java +++ b/modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java @@ -46,7 +46,7 @@ public void extensionsTest(String methodName, .flatMap(response -> Arrays.stream(response.headers())).toArray(Header[]::new); final Optional> optionalMap = - AnnotationsUtils.getHeaders(headers,null, null); + AnnotationsUtils.getHeaders(headers, null, null); Assert.assertEquals(optionalMap, expected); } From cc14df5be0c8fbf7e348ddaea153e9d338340c92 Mon Sep 17 00:00:00 2001 From: MicRyc Date: Thu, 1 Feb 2024 12:03:49 +0100 Subject: [PATCH 12/13] Add space after coma --- .../src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index 566e94af13..9534e426fc 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1311,7 +1311,7 @@ public static Optional> getHeaders(io.swagger.v3.oas.annotat } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation) { - return getHeader(header,null, jsonViewAnnotation); + return getHeader(header, null, jsonViewAnnotation); } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, Components components, JsonView jsonViewAnnotation) { return getHeader(header, components, jsonViewAnnotation, false); From 5e157edf13e993123bd574e9c05210ba56899113 Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 1 Feb 2024 13:13:36 +0100 Subject: [PATCH 13/13] Refs #4196 - reintroduce original getHeader(s) methods signatures --- .../java/io/swagger/v3/core/util/AnnotationsUtils.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java index 9534e426fc..bd19af4b6b 100644 --- a/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java @@ -1294,6 +1294,10 @@ public static Optional> getHeaders(io.swagger.v3.oas.annotat return getHeaders(annotationHeaders, components, jsonViewAnnotation, false); } + public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, JsonView jsonViewAnnotation, boolean openapi31) { + return getHeaders(annotationHeaders, null, jsonViewAnnotation, openapi31); + } + public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (annotationHeaders == null) { return Optional.empty(); @@ -1317,6 +1321,9 @@ public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.H return getHeader(header, components, jsonViewAnnotation, false); } + public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation, boolean openapi31) { + return getHeader(header, null, jsonViewAnnotation, openapi31); + } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (header == null || header.hidden()) {