Skip to content

Commit

Permalink
refs #3080 - support array in additionalProperties annotation member
Browse files Browse the repository at this point in the history
  • Loading branch information
frantuma committed Sep 17, 2023
1 parent cbb955b commit 33b9b95
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,23 @@
SchemaProperty[] schemaProperties() default {};

/**
* The schema properties defined for schema provided in @Schema
* The additionalProperties schema defined for schema provided in @Schema
* If the additionalProperties schema is an array, use additionalPropertiesArraySchema
*
* @since 2.2.0
* @return the schema properties
* @return the additionalProperties schema
*/
Schema additionalPropertiesSchema() default @Schema();

/**
* The additionalProperties array schema defined for schema provided in @Schema
* If the additionalProperties schema is not an array, use additionalPropertiesSchema
*
* @since 2.2.16
* @return the additionalProperties array schema
*/
ArraySchema additionalPropertiesArraySchema() default @ArraySchema();

/**
* The schema of the array that defines the type used for the content.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,9 @@ public static Optional<ArraySchema> getArraySchema(io.swagger.v3.oas.annotations
return Optional.empty();
}
public static Optional<Schema> getArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, Components components, JsonView jsonViewAnnotation, boolean openapi31, Schema existingSchema) {
return getArraySchema(arraySchema, components, jsonViewAnnotation, openapi31, existingSchema, false);
}
public static Optional<Schema> getArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, Components components, JsonView jsonViewAnnotation, boolean openapi31, Schema existingSchema, boolean processSchemaImplementation) {
if (arraySchema == null || !hasArrayAnnotation(arraySchema)) {
if (existingSchema == null) {
return Optional.empty();
Expand Down Expand Up @@ -546,7 +549,9 @@ public static Optional<Schema> getArraySchema(io.swagger.v3.oas.annotations.medi
if (arraySchema.schema() != null) {
if (arraySchema.schema().implementation().equals(Void.class)) {
getSchemaFromAnnotation(arraySchema.schema(), components, jsonViewAnnotation, openapi31).ifPresent(arraySchemaObject::setItems);
} // if present, schema implementation handled upstream
} else if (processSchemaImplementation) {
getSchema(arraySchema.schema(), arraySchema, false, arraySchema.schema().implementation(), components, jsonViewAnnotation, openapi31).ifPresent(arraySchemaObject::setItems);
}
}

return Optional.of(arraySchemaObject);
Expand Down Expand Up @@ -1500,7 +1505,15 @@ public static Optional<Content> getContent(io.swagger.v3.oas.annotations.media.C

}
}
if (
Optional<Schema> arraySchemaResult = getArraySchema(annotationContent.additionalPropertiesArraySchema(), components, jsonViewAnnotation, openapi31, null, true);
if (arraySchemaResult.isPresent()) {
if ("array".equals(mediaType.getSchema().getType())) {
mediaType.getSchema().getItems().additionalProperties(arraySchemaResult.get());
} else {
mediaType.getSchema().additionalProperties(arraySchemaResult.get());
}
} else {
if (
hasSchemaAnnotation(annotationContent.additionalPropertiesSchema()) &&
mediaType.getSchema() != null &&
!Boolean.TRUE.equals(mediaType.getSchema().getAdditionalProperties()) &&
Expand All @@ -1514,6 +1527,7 @@ public static Optional<Content> getContent(io.swagger.v3.oas.annotations.media.C
}
}
);
}
}
} else {
mediaType.setSchema(schema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.swagger.v3.jaxrs2.resources.Misc31Resource;
import io.swagger.v3.jaxrs2.resources.ParameterMaximumValueResource;
import io.swagger.v3.jaxrs2.resources.ResponseReturnTypeResource;
import io.swagger.v3.jaxrs2.resources.SchemaAdditionalPropertiesResource;
import io.swagger.v3.jaxrs2.resources.SchemaPropertiesResource;
import io.swagger.v3.jaxrs2.resources.SiblingPropResource;
import io.swagger.v3.jaxrs2.resources.SiblingsResource;
Expand Down Expand Up @@ -3011,6 +3012,75 @@ public void testSchemaProperties() {
SerializationMatchers.assertEqualsToYaml(openAPI, yaml);
}

@Test(description = "Test Schema AdditionalProperties annotations")
public void testSchemaAdditionalProperties() {
Reader reader = new Reader(new OpenAPI());

OpenAPI openAPI = reader.read(SchemaAdditionalPropertiesResource.class);
String yaml = "openapi: 3.0.1\n" +
"paths:\n" +
" /arraySchemaImpl:\n" +
" get:\n" +
" operationId: arraySchemaImpl\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" type: object\n" +
" additionalProperties:\n" +
" type: array\n" +
" items:\n" +
" $ref: '#/components/schemas/Pet'\n" +
" /fromtResponseType:\n" +
" get:\n" +
" operationId: fromtResponseType\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" type: object\n" +
" additionalProperties:\n" +
" type: array\n" +
" items:\n" +
" $ref: '#/components/schemas/Pet'\n" +
" /schemaImpl:\n" +
" get:\n" +
" operationId: schemaImpl\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" type: object\n" +
" additionalProperties:\n" +
" $ref: '#/components/schemas/Pet'\n" +
" /schemaNotImpl:\n" +
" get:\n" +
" operationId: schemaNotImpl\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" type: object\n" +
" additionalProperties:\n" +
" $ref: '#/components/schemas/Pet'\n" +
"components:\n" +
" schemas:\n" +
" Pet:\n" +
" type: object\n" +
" properties:\n" +
" foo:\n" +
" type: string\n";
SerializationMatchers.assertEqualsToYaml(openAPI, yaml);
}

@Test(description = "Responses schema resolved from return type")
public void testResponseReturnType() {
Reader reader = new Reader(new OpenAPI());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package io.swagger.v3.jaxrs2.resources;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Map;

public class SchemaAdditionalPropertiesResource {

static class Pet {
public String foo;
}
@GET
@Path("/fromtResponseType")
public Map<String, List<Pet>> fromtResponseType() {
return null;
}

@GET
@Path("/schemaNotImpl")
@Operation(
operationId = "schemaNotImpl",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
content = @Content(
mediaType = "application/json",
schema = @Schema(
type = "object"
),
additionalPropertiesSchema = @Schema(
ref = "#/components/schemas/Pet"
)
)
)
}
)
public Response schemaNotImpl() {
return null;
}

@GET
@Path("/schemaImpl")
@Operation(
operationId = "schemaImpl",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
content = @Content(
mediaType = "application/json",
schema = @Schema(
type = "object",
additionalPropertiesSchema = Pet.class
)
)
)
}
)
public Response schemaImpl() {
return null;
}

@GET
@Path("/arraySchemaImpl")
@Operation(
operationId = "arraySchemaImpl",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
content = @Content(
mediaType = "application/json",
additionalPropertiesArraySchema = @ArraySchema(
schema = @Schema(
implementation = Pet.class
)
),
schema = @Schema(
type = "object"
)
)
)
}
)
public Response arraySchemaImpl() {
return null;
}

}

0 comments on commit 33b9b95

Please sign in to comment.