Skip to content

Commit

Permalink
fix siblings in response and request body schemas OAS 3.1 resolving
Browse files Browse the repository at this point in the history
  • Loading branch information
frantuma committed Jun 27, 2023
1 parent 306905c commit 836eaaf
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
Expand Down Expand Up @@ -1214,27 +1215,61 @@ protected Content resolveEmptyContent(Produces classProduces, Produces methodPro
return content;
}

private MediaType clone(MediaType mediaType) {
if(mediaType == null)
return mediaType;
try {
if(config.isOpenAPI31()) {
mediaType = Json31.mapper().readValue(Json31.pretty(mediaType), MediaType.class);
} else {
mediaType = Json.mapper().readValue(Json.pretty(mediaType), MediaType.class);
}
} catch (IOException e) {
LOGGER.error("Could not clone mediaType", e);
}
return mediaType;
}
private Schema clone(Schema schema) {
if(schema == null)
return schema;
try {
String cloneName = schema.getName();
if(config.isOpenAPI31()) {
schema = Json31.mapper().readValue(Json31.pretty(schema), Schema.class);
} else {
schema = Json.mapper().readValue(Json.pretty(schema), Schema.class);
}
schema.setName(cloneName);
} catch (IOException e) {
LOGGER.error("Could not clone schema", e);
}
return schema;
}

protected void resolveResponseSchemaFromReturnType(
Operation operation,
io.swagger.v3.oas.annotations.responses.ApiResponse[] responses,
Schema schema,
Produces classProduces, Produces methodProduces) {
if (responses != null) {
for (io.swagger.v3.oas.annotations.responses.ApiResponse response: responses) {
Map<String, MediaType> reresolvedMediaTypes = new LinkedHashMap<>();
if (response.useReturnTypeSchema()) {
ApiResponse opResponse = operation.getResponses().get(response.responseCode());
if (opResponse != null) {
if (opResponse.getContent() != null) {
for (String key : opResponse.getContent().keySet()) {
MediaType mediaType = opResponse.getContent().get(key);
MediaType mediaType = clone(opResponse.getContent().get(key));
Schema existingSchema = clone(schema);
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);
Optional<Schema> reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(content.get().schema(), components, null, config.isOpenAPI31(), existingSchema);
if (reResolvedSchema.isPresent()) {
schema = reResolvedSchema.get();
existingSchema = reResolvedSchema.get();
}
}
mediaType.schema(schema);
mediaType.schema(existingSchema);
reresolvedMediaTypes.put(key, mediaType);
}
} else {
Content content = resolveEmptyContent(classProduces, methodProduces);
Expand All @@ -1244,6 +1279,7 @@ protected void resolveResponseSchemaFromReturnType(
opResponse.content(content);
}
}
opResponse.getContent().putAll(reresolvedMediaTypes);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import io.swagger.v3.jaxrs2.resources.SchemaPropertiesResource;
import io.swagger.v3.jaxrs2.resources.SiblingsResource;
import io.swagger.v3.jaxrs2.resources.SiblingsResourceRequestBody;
import io.swagger.v3.jaxrs2.resources.SiblingsResourceRequestBodyMultiple;
import io.swagger.v3.jaxrs2.resources.SiblingsResourceResponse;
import io.swagger.v3.jaxrs2.resources.SiblingsResourceSimple;
import io.swagger.v3.jaxrs2.resources.SingleExampleResource;
import io.swagger.v3.jaxrs2.resources.BasicFieldsResource;
Expand Down Expand Up @@ -3510,6 +3512,54 @@ public void testSiblingsOnResource() {
SerializationMatchers.assertEqualsToYaml31(openAPI, yaml);
}

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

OpenAPI openAPI = reader.read(SiblingsResourceResponse.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" +
" application/json:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet\n" +
" readOnly: true\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet xml\n" +
" readOnly: true\n" +
" /test/impl:\n" +
" get:\n" +
" operationId: getCartImpl\n" +
" responses:\n" +
" \"300\":\n" +
" description: aaa\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet\n" +
" readOnly: true\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet xml\n" +
" readOnly: true\n" +
"components:\n" +
" schemas:\n" +
" PetSimple:\n" +
" description: Pet\n";
SerializationMatchers.assertEqualsToYaml31(openAPI, yaml);
}

@Test
public void testSiblingsOnResourceRequestBody() {
Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true));
Expand Down Expand Up @@ -3554,4 +3604,59 @@ public void testSiblingsOnResourceRequestBody() {
" description: Pet\n";
SerializationMatchers.assertEqualsToYaml31(openAPI, yaml);
}

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

OpenAPI openAPI = reader.read(SiblingsResourceRequestBodyMultiple.class);
String yaml = "openapi: 3.1.0\n" +
"paths:\n" +
" /test/bodyimpl:\n" +
" get:\n" +
" operationId: getBodyImpl\n" +
" requestBody:\n" +
" description: aaa\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet\n" +
" writeOnly: true\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet xml\n" +
" writeOnly: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" '*/*': {}\n" +
" /test/bodyimplparam:\n" +
" get:\n" +
" operationId: getBodyImplParam\n" +
" requestBody:\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet\n" +
" writeOnly: true\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet xml\n" +
" writeOnly: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" '*/*': {}\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,58 @@
package io.swagger.v3.jaxrs2.resources;

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.parameters.RequestBody;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/test")
public class SiblingsResourceRequestBodyMultiple {
@Path("/bodyimpl")
@GET
@Operation(
requestBody =
@RequestBody(
description = "aaa",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(
description = "resource pet",
implementation = PetSimple.class,
accessMode = Schema.AccessMode.WRITE_ONLY)),
@Content(
mediaType = "application/xml",
schema = @Schema(
description = "resource pet xml",
implementation = PetSimple.class,
accessMode = Schema.AccessMode.WRITE_ONLY))
}))
public Response getBodyImpl(Object body) {
return null;
}

@Path("/bodyimplparam")
@GET
public Response getBodyImplParam(@RequestBody(
content = {
@Content(
mediaType = "application/json",
schema = @Schema(
description = "resource pet",
implementation = PetSimple.class,
accessMode = Schema.AccessMode.WRITE_ONLY)),
@Content(
mediaType = "application/xml",
schema = @Schema(
description = "resource pet xml",
implementation = PetSimple.class,
accessMode = Schema.AccessMode.WRITE_ONLY))
}) Object body) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.swagger.v3.jaxrs2.resources;

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 SiblingsResourceResponse {
@GET
@Operation(
responses = {
@ApiResponse(
responseCode = "300",
description = "aaa",
useReturnTypeSchema = true,
content = {
@Content(
mediaType = "application/json",
schema = @Schema(
description = "resource pet",
accessMode = Schema.AccessMode.READ_ONLY)),
@Content(
mediaType = "application/xml",
schema = @Schema(
description = "resource pet xml",
accessMode = Schema.AccessMode.READ_ONLY))
})})
public PetSimple getCart() {
return null;
}

@Path("/impl")
@GET
@Operation(
responses = {
@ApiResponse(
responseCode = "300",
description = "aaa",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(
description = "resource pet",
implementation = PetSimple.class,
accessMode = Schema.AccessMode.READ_ONLY)),
@Content(
mediaType = "application/xml",
schema = @Schema(
description = "resource pet xml",
implementation = PetSimple.class,
accessMode = Schema.AccessMode.READ_ONLY))
})})
public PetSimple getCartImpl() {
return null;
}

}

0 comments on commit 836eaaf

Please sign in to comment.