Skip to content

Commit

Permalink
enhance OAS 3.1 resolving and allow siblings in response schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
frantuma committed Jun 26, 2023
1 parent 63aece7 commit 800fb35
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,24 @@
@OpenAPI31
String $anchor() default "";

/**
* Provides the $vocabulary related to schema
*
* @since 2.2.14 / OpenAPI 3.1
* @return $vocabulary schema
*/
@OpenAPI31
String $vocabulary() default "";

/**
* Provides the $dynamicAnchor related to schema
*
* @since 2.2.14 / OpenAPI 3.1
* @return $dynamicAnchor schema
*/
@OpenAPI31
String $dynamicAnchor() default "";

/**
* Provides the content encoding related to this schema
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2386,6 +2386,20 @@ protected String resolveId(Annotated a, Annotation[] annotations, io.swagger.v3.
return null;
}

protected String resolve$vocabulary(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) {
if (schema != null && StringUtils.isNotBlank(schema.$vocabulary())) {
return schema.$vocabulary();
}
return null;
}

protected String resolve$dynamicAnchor(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) {
if (schema != null && StringUtils.isNotBlank(schema.$dynamicAnchor())) {
return schema.$dynamicAnchor();
}
return null;
}

protected String resolveContentEncoding(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) {
if (schema != null && StringUtils.isNotBlank(schema.contentEncoding())) {
return schema.contentEncoding();
Expand Down Expand Up @@ -2567,16 +2581,24 @@ protected void resolveSchemaMembers(Schema schema, AnnotatedType annotatedType,
thenSchema = buildRefSchemaIfObject(thenSchema, context);
schema.setThen(thenSchema);
}
if (!Void.class.equals(schemaAnnotation.contentSchema())) {
Schema contentSchema = resolve(new AnnotatedType(schemaAnnotation.contentSchema()), context, next);
contentSchema = buildRefSchemaIfObject(contentSchema, context);
schema.setContentSchema(contentSchema);
}
if (!Void.class.equals(schemaAnnotation.unevaluatedProperties())) {
Schema unevaluatedProperties = resolve(new AnnotatedType(schemaAnnotation.unevaluatedProperties()), context, next);
unevaluatedProperties = buildRefSchemaIfObject(unevaluatedProperties, context);
schema.setUnevaluatedProperties(unevaluatedProperties);
}

if (schemaAnnotation.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.TRUE)) {
schema.additionalProperties(true);
} else if (schemaAnnotation.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.FALSE)) {
schema.additionalProperties(false);
} else {
if (!schemaAnnotation.additionalPropertiesSchema().equals(Void.class)) {
Schema additionalPropertiesSchema = resolve(new AnnotatedType(schemaAnnotation.additionalPropertiesSchema()), context, next);
additionalPropertiesSchema = buildRefSchemaIfObject(additionalPropertiesSchema, context);
schema.additionalProperties(additionalPropertiesSchema);
}
}

final Map<String, List<String>> dependentRequired = resolveDependentRequired(a, annotations, schemaAnnotation);
if (dependentRequired != null && !dependentRequired.isEmpty()) {
schema.setDependentRequired(dependentRequired);
Expand Down Expand Up @@ -2739,6 +2761,14 @@ protected void resolveSchemaMembers(Schema schema, Annotated a, Annotation[] ann
if ($comment != null) {
schema.set$comment($comment);
}
String $vocabulary = resolve$vocabulary(a, annotations, schemaAnnotation);
if ($vocabulary != null) {
schema.set$vocabulary($vocabulary);
}
String $dynamicAnchor = resolve$dynamicAnchor(a, annotations, schemaAnnotation);
if ($dynamicAnchor != null) {
schema.$dynamicAnchor($dynamicAnchor);
}
String contentEncoding = resolveContentEncoding(a, annotations, schemaAnnotation);
if (contentEncoding != null) {
schema.setContentEncoding(contentEncoding);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,9 @@ public static Optional<Schema> getSchemaFromAnnotation(
}
Schema schemaObject = null;
if (!openapi31) {
if (existingSchema != null) {
return Optional.of(existingSchema);
}
if (schema.oneOf().length > 0 ||
schema.allOf().length > 0 ||
schema.anyOf().length > 0) {
Expand Down Expand Up @@ -597,6 +600,12 @@ public static Optional<Schema> getSchemaFromAnnotation(
if (StringUtils.isNotBlank(schema.$anchor())) {
schemaObject.set$anchor(schema.$anchor());
}
if (StringUtils.isNotBlank(schema.$vocabulary())) {
schemaObject.set$vocabulary(schema.$vocabulary());
}
if (StringUtils.isNotBlank(schema.$dynamicAnchor())) {
schemaObject.set$dynamicAnchor(schema.$dynamicAnchor());
}
if (StringUtils.isNotBlank(schema.contentEncoding())) {
schemaObject.setContentEncoding(schema.contentEncoding());
}
Expand Down Expand Up @@ -810,6 +819,9 @@ public static Schema resolveSchemaFromType(Class<?> schemaImplementation, Compon
}

public static Schema resolveSchemaFromType(Class<?> schemaImplementation, Components components, JsonView jsonViewAnnotation, boolean openapi31) {
return resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null);
}
public static Schema resolveSchemaFromType(Class<?> schemaImplementation, Components components, JsonView jsonViewAnnotation, boolean openapi31, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, io.swagger.v3.oas.annotations.media.ArraySchema arrayAnnotation) {
Schema schemaObject;
PrimitiveType primitiveType = PrimitiveType.fromType(schemaImplementation);
if (primitiveType != null) {
Expand All @@ -836,6 +848,10 @@ public static Schema resolveSchemaFromType(Class<?> schemaImplementation, Compon
}
}
}
Optional<Schema> reResolvedSchema = getSchemaFromAnnotation(schemaAnnotation, components, jsonViewAnnotation, openapi31, schemaObject);
if (reResolvedSchema.isPresent()) {
schemaObject = reResolvedSchema.get();
}
if (StringUtils.isBlank(schemaObject.get$ref()) && StringUtils.isBlank(schemaObject.getType())) {
// default to string
schemaObject.setType("string");
Expand Down Expand Up @@ -1531,7 +1547,7 @@ public static Optional<? extends Schema> getSchema(io.swagger.v3.oas.annotations
JsonView jsonViewAnnotation,
boolean openapi31) {
if (schemaImplementation != Void.class) {
Schema schemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31);
Schema schemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, schemaAnnotation, arrayAnnotation);
if (StringUtils.isNotBlank(schemaAnnotation.format())) {
schemaObject.setFormat(schemaAnnotation.format());
}
Expand Down Expand Up @@ -2237,6 +2253,22 @@ public Class<?> contains() {
return patch.$anchor();
}

@Override
public String $vocabulary() {
if (StringUtils.isNotBlank(master.$vocabulary()) || StringUtils.isBlank(patch.$vocabulary())) {
return master.$vocabulary();
}
return patch.$vocabulary();
}

@Override
public String $dynamicAnchor() {
if (StringUtils.isNotBlank(master.$dynamicAnchor()) || StringUtils.isBlank(patch.$dynamicAnchor())) {
return master.$dynamicAnchor();
}
return patch.$dynamicAnchor();
}

@Override
public String contentEncoding() {
if (StringUtils.isNotBlank(master.contentEncoding()) || StringUtils.isBlank(patch.contentEncoding())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1225,7 +1225,15 @@ protected void resolveResponseSchemaFromReturnType(
ApiResponse opResponse = operation.getResponses().get(response.responseCode());
if (opResponse != null) {
if (opResponse.getContent() != null) {
for (MediaType mediaType : opResponse.getContent().values()) {
for (String key : opResponse.getContent().keySet()) {
MediaType mediaType = opResponse.getContent().get(key);
Optional<io.swagger.v3.oas.annotations.media.Content> content = Arrays.stream(response.content()).filter(c -> c.mediaType().equals(key)).findFirst();
if (content.isPresent()) {
Optional<Schema> reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(content.get().schema(), components, null, config.isOpenAPI31(), schema);
if (reResolvedSchema.isPresent()) {
schema = reResolvedSchema.get();
}
}
mediaType.schema(schema);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.swagger.v3.jaxrs2.resources.ResponseReturnTypeResource;
import io.swagger.v3.jaxrs2.resources.SchemaPropertiesResource;
import io.swagger.v3.jaxrs2.resources.SiblingsResource;
import io.swagger.v3.jaxrs2.resources.SiblingsResourceSimple;
import io.swagger.v3.jaxrs2.resources.SingleExampleResource;
import io.swagger.v3.jaxrs2.resources.BasicFieldsResource;
import io.swagger.v3.jaxrs2.resources.BookStoreTicket2646;
Expand Down Expand Up @@ -3469,4 +3470,42 @@ public void testSiblings() {
" description: child\n";
SerializationMatchers.assertEqualsToYaml31(openAPI, yaml);
}

@Test
public void testSiblingsOnResource() {
Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true));

OpenAPI openAPI = reader.read(SiblingsResourceSimple.class);
String yaml = "openapi: 3.1.0\n" +
"paths:\n" +
" /test:\n" +
" get:\n" +
" operationId: getCart\n" +
" responses:\n" +
" \"300\":\n" +
" description: aaa\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet\n" +
" readOnly: true\n" +
" /test/impl:\n" +
" get:\n" +
" operationId: getCartImpl\n" +
" responses:\n" +
" \"300\":\n" +
" description: aaa\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet\n" +
" readOnly: true\n" +
"components:\n" +
" schemas:\n" +
" PetSimple:\n" +
" description: Pet\n";
SerializationMatchers.assertEqualsToYaml31(openAPI, yaml);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.swagger.v3.jaxrs2.resources;

import io.swagger.v3.jaxrs2.resources.siblings.Pet;
import io.swagger.v3.jaxrs2.resources.siblings.PetSimple;
import io.swagger.v3.oas.annotations.Operation;
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;

@Path("/test")
public class SiblingsResourceSimple {
@GET
@Operation(
responses = {
@ApiResponse(
responseCode = "300",
description = "aaa",
useReturnTypeSchema = true,
content = {
@Content(
mediaType = "*/*",
schema = @Schema(
description = "resource pet",
accessMode = Schema.AccessMode.READ_ONLY))
})})
public PetSimple getCart() {
return null;
}

@Path("/impl")
@GET
@Operation(
responses = {
@ApiResponse(
responseCode = "300",
description = "aaa",
content = {
@Content(
mediaType = "*/*",
schema = @Schema(
description = "resource pet",
implementation = PetSimple.class,
accessMode = Schema.AccessMode.READ_ONLY))
})})
public PetSimple getCartImpl() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.swagger.v3.jaxrs2.resources.siblings;

import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "Pet")
public class PetSimple {

}
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ public Schema specVersion(SpecVersion specVersion) {
private String $anchor;

/**
* @since 2.2.8 (OpenAPI 3.1.0)
* @since 2.2.14 (OpenAPI 3.1.0)
*/
@OpenAPI31
private String $vocabulary;

/**
* @since 2.2.8 (OpenAPI 3.1.0)
* @since 2.2.14 (OpenAPI 3.1.0)
*/
@OpenAPI31
private String $dynamicAnchor;
Expand Down

0 comments on commit 800fb35

Please sign in to comment.