From c5415e5ef1f49c65f677225b0751c35f18b2d1d8 Mon Sep 17 00:00:00 2001 From: Stephen Webb Date: Tue, 19 Apr 2022 15:03:35 +0100 Subject: [PATCH 1/2] Prefer ComposedSchemas over non-composed so that method name order doesn't prevent polymorphic links generating into the spec --- .../core/SpringDocAnnotationsUtils.java | 13 ++- .../test/org/springdoc/api/app31/Cat.java | 24 +++++ .../test/org/springdoc/api/app31/Dog.java | 24 +++++ .../test/org/springdoc/api/app31/Pet.java | 23 ++++ .../springdoc/api/app31/PetController.java | 18 ++++ .../api/app31/SpringDocApp31Test.java | 12 +++ .../src/test/resources/results/app31.json | 100 ++++++++++++++++++ 7 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Cat.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Dog.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Pet.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/PetController.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/SpringDocApp31Test.java create mode 100644 springdoc-openapi-data-rest/src/test/resources/results/app31.json diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java index 29107047f..e40134335 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java @@ -129,9 +129,16 @@ public static Schema extractSchema(Components components, Type returnType, JsonV componentSchemas.putAll(schemaMap); } else - for (Map.Entry entry : schemaMap.entrySet()) - if (!componentSchemas.containsKey(entry.getKey())) - componentSchemas.put(entry.getKey(), entry.getValue()); + for (Map.Entry entry : schemaMap.entrySet()) { + if (!componentSchemas.containsKey(entry.getKey())) { + componentSchemas.put(entry.getKey(), entry.getValue()); + // If we've seen this schema before but find later it should be polymorphic, + // replace the existing schema with this richer version. + } else if (entry.getValue() instanceof ComposedSchema && + !(componentSchemas.get(entry.getKey()) instanceof ComposedSchema)) { + componentSchemas.put(entry.getKey(), entry.getValue()); + } + } components.setSchemas(componentSchemas); } if (resolvedSchema.schema != null) { diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Cat.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Cat.java new file mode 100644 index 000000000..5143cdd12 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Cat.java @@ -0,0 +1,24 @@ +package test.org.springdoc.api.app31; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema +public class Cat extends Pet { + + private final boolean meows; + + public Cat() { + super(); + this.meows = false; + } + + public Cat(boolean meows, String name) { + super(name); + this.meows = meows; + } + + public boolean getMeows() { + return meows; + } + +} diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Dog.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Dog.java new file mode 100644 index 000000000..6c8598b31 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Dog.java @@ -0,0 +1,24 @@ +package test.org.springdoc.api.app31; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema +public class Dog extends Pet { + + private final boolean barks; + + public Dog() { + super(); + this.barks = false; + } + + public Dog(boolean barks, String name) { + super(name); + this.barks = barks; + } + + public boolean getBarks() { + return barks; + } + +} diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Pet.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Pet.java new file mode 100644 index 000000000..dd3c228db --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/Pet.java @@ -0,0 +1,23 @@ +package test.org.springdoc.api.app31; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(Dog.class), + @JsonSubTypes.Type(Cat.class) +}) +public class Pet { + + public final String name; + + public Pet() { + this.name = null; + } + + public Pet(String name) { + this.name = name; + } + +} diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/PetController.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/PetController.java new file mode 100644 index 000000000..38d320d90 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/PetController.java @@ -0,0 +1,18 @@ +package test.org.springdoc.api.app31; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class PetController { + + @GetMapping("/any") + public Pet getAnyPet() { + return new Cat(true, "cat"); + } + + @GetMapping("/dog") + public Dog getDog() { + return new Dog(true, "dog"); + } +} diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/SpringDocApp31Test.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/SpringDocApp31Test.java new file mode 100644 index 000000000..5a4f65661 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app31/SpringDocApp31Test.java @@ -0,0 +1,12 @@ +package test.org.springdoc.api.app31; + +import test.org.springdoc.api.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp31Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp {} + +} \ No newline at end of file diff --git a/springdoc-openapi-data-rest/src/test/resources/results/app31.json b/springdoc-openapi-data-rest/src/test/resources/results/app31.json new file mode 100644 index 000000000..edc0fc551 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/resources/results/app31.json @@ -0,0 +1,100 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [{ + "url": "http://localhost", + "description": "Generated server url" + }], + "paths": { + "/dog": { + "get": { + "tags": ["pet-controller"], + "operationId": "getDog", + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/Dog" + } + } + } + } + } + } + }, + "/any": { + "get": { + "tags": ["pet-controller"], + "operationId": "getAnyPet", + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "oneOf": [{ + "$ref": "#/components/schemas/Pet" + }, { + "$ref": "#/components/schemas/Cat" + }, { + "$ref": "#/components/schemas/Dog" + }] + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Dog": { + "type": "object", + "allOf": [{ + "$ref": "#/components/schemas/Pet" + }, { + "type": "object", + "properties": { + "barks": { + "type": "boolean" + } + } + }] + }, + "Cat": { + "type": "object", + "allOf": [{ + "$ref": "#/components/schemas/Pet" + }, { + "type": "object", + "properties": { + "meows": { + "type": "boolean" + } + } + }] + }, + "Pet": { + "required": ["type"], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "discriminator": { + "propertyName": "type" + } + } + } + } +} \ No newline at end of file From dd16cd06ca70236a4c5e27306873c95d67d800d3 Mon Sep 17 00:00:00 2001 From: Stephen Webb Date: Wed, 20 Apr 2022 09:40:42 +0100 Subject: [PATCH 2/2] fix whitespace formatting --- .../core/SpringDocAnnotationsUtils.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java index e40134335..0a3527ffc 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocAnnotationsUtils.java @@ -130,15 +130,15 @@ public static Schema extractSchema(Components components, Type returnType, JsonV } else for (Map.Entry entry : schemaMap.entrySet()) { - if (!componentSchemas.containsKey(entry.getKey())) { - componentSchemas.put(entry.getKey(), entry.getValue()); - // If we've seen this schema before but find later it should be polymorphic, - // replace the existing schema with this richer version. - } else if (entry.getValue() instanceof ComposedSchema && - !(componentSchemas.get(entry.getKey()) instanceof ComposedSchema)) { - componentSchemas.put(entry.getKey(), entry.getValue()); - } - } + if (!componentSchemas.containsKey(entry.getKey())) { + componentSchemas.put(entry.getKey(), entry.getValue()); + // If we've seen this schema before but find later it should be polymorphic, + // replace the existing schema with this richer version. + } else if (entry.getValue() instanceof ComposedSchema && + !(componentSchemas.get(entry.getKey()) instanceof ComposedSchema)) { + componentSchemas.put(entry.getKey(), entry.getValue()); + } + } components.setSchemas(componentSchemas); } if (resolvedSchema.schema != null) {