Skip to content

Commit

Permalink
Merge pull request #2902 from swagger-api/ticket-2900
Browse files Browse the repository at this point in the history
ref #2900 - supports primitives in oneOf, anyOf, allOf schema annotations
  • Loading branch information
frantuma authored Aug 9, 2018
2 parents 2f3e488 + 608ffeb commit 9962469
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,12 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
return context.resolve(aType);
}

List<Class<?>> composedSchemaReferencedClasses = getComposedSchemaReferencedClasses(type.getRawClass(), annotatedType.getCtxAnnotations());
List<Class<?>> composedSchemaReferencedClasses = getComposedSchemaReferencedClasses(type.getRawClass(), annotatedType.getCtxAnnotations(), resolvedSchemaAnnotation);
boolean isComposedSchema = composedSchemaReferencedClasses != null;

if (type.isContainerType()) {
// TODO currently a MapSchema or ArraySchema don't also support composed schema props (oneOf,..)
isComposedSchema = false;
JavaType keyType = type.getKeyType();
JavaType valueType = type.getContentType();
String pName = null;
Expand Down Expand Up @@ -752,10 +754,16 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
.collect(Collectors.toList());
oneOfFiltered.forEach(c -> {
Schema oneOfRef = context.resolve(new AnnotatedType().type(c).jsonViewAnnotation(annotatedType.getJsonViewAnnotation()));
composedSchema.addOneOfItem(new Schema().$ref(oneOfRef.getName()));
// remove shared properties defined in the parent
if (isSubtype(beanDesc.getClassInfo(), c)) {
removeParentProperties(composedSchema, oneOfRef);
if (oneOfRef != null) {
if (StringUtils.isBlank(oneOfRef.getName())) {
composedSchema.addOneOfItem(oneOfRef);
} else {
composedSchema.addOneOfItem(new Schema().$ref(oneOfRef.getName()));
}
// remove shared properties defined in the parent
if (isSubtype(beanDesc.getClassInfo(), c)) {
removeParentProperties(composedSchema, oneOfRef);
}
}

});
Expand Down Expand Up @@ -844,22 +852,26 @@ protected boolean ignore(final Annotated member, final XmlAccessorType xmlAccess

private void handleUnwrapped(List<Schema> props, Schema innerModel, String prefix, String suffix) {
if (StringUtils.isBlank(suffix) && StringUtils.isBlank(prefix)) {
props.addAll(innerModel.getProperties().values());
if (innerModel.getProperties() != null) {
props.addAll(innerModel.getProperties().values());
}
} else {
if (prefix == null) {
prefix = "";
}
if (suffix == null) {
suffix = "";
}
for (Schema prop : (Collection<Schema>) innerModel.getProperties().values()) {
try {
Schema clonedProp = Json.mapper().readValue(Json.pretty(prop), Schema.class);
clonedProp.setName(prefix + prop.getName() + suffix);
props.add(clonedProp);
} catch (IOException e) {
LOGGER.error("Exception cloning property", e);
return;
if (innerModel.getProperties() != null) {
for (Schema prop : (Collection<Schema>) innerModel.getProperties().values()) {
try {
Schema clonedProp = Json.mapper().readValue(Json.pretty(prop), Schema.class);
clonedProp.setName(prefix + prop.getName() + suffix);
props.add(clonedProp);
} catch (IOException e) {
LOGGER.error("Exception cloning property", e);
return;
}
}
}
}
Expand Down Expand Up @@ -1217,12 +1229,7 @@ private void removeParentProperties(Schema child, Schema parent) {
}
}

protected List<Class<?>> getComposedSchemaReferencedClasses(Class<?> clazz, Annotation[] ctxAnnotations) {

io.swagger.v3.oas.annotations.media.Schema schemaAnnotation = AnnotationsUtils.getSchemaAnnotation(ctxAnnotations);
if (schemaAnnotation == null) {
schemaAnnotation = AnnotationsUtils.getSchemaDeclaredAnnotation(clazz);
}
protected List<Class<?>> getComposedSchemaReferencedClasses(Class<?> clazz, Annotation[] ctxAnnotations, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation) {

if (schemaAnnotation != null) {
Class<?>[] allOf = schemaAnnotation.allOf();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ public Schema createProperty() {
return new NumberSchema();
}
},
NUMBER(Number.class, "number") {
@Override
public Schema createProperty() {
return new NumberSchema();
}
},
DATE(DateStub.class, "date") {
@Override
public DateSchema createProperty() {
Expand Down Expand Up @@ -185,6 +191,7 @@ public Schema createProperty() {
addKeys(keyClasses, DOUBLE, Double.class, Double.TYPE);
addKeys(keyClasses, INTEGER, java.math.BigInteger.class);
addKeys(keyClasses, DECIMAL, java.math.BigDecimal.class);
addKeys(keyClasses, NUMBER, Number.class);
addKeys(keyClasses, DATE, DateStub.class);
addKeys(keyClasses, DATE_TIME, java.util.Date.class);
addKeys(keyClasses, FILE, java.io.File.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import io.swagger.v3.core.resolving.resources.TestObject2616;
import io.swagger.v3.core.resolving.resources.TestObjectTicket2620;
import io.swagger.v3.core.resolving.resources.TestObjectTicket2620Subtypes;
import io.swagger.v3.core.resolving.resources.TestObjectTicket2900;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.Schema;
Expand Down Expand Up @@ -56,6 +58,31 @@ public void readBilateralComposedSchema_ticket2620() {
Assert.assertTrue(((ComposedSchema)model).getOneOf().size() == 2);
}

@Test(description = "read composed schem refs #2900")
public void readComposedSchema_ticket2900() {
Json.mapper().addMixIn(TestObjectTicket2900.GsonJsonPrimitive.class, TestObjectTicket2900.GsonJsonPrimitiveMixIn.class);
Map<String, Schema> schemas = ModelConverters.getInstance().readAll(TestObjectTicket2900.class);
Schema model = schemas.get("SomeDTO");
Assert.assertNotNull(model);
Map<String, Schema> properties = model.getProperties();
Assert.assertNotNull(properties.get("value"));
Assert.assertEquals(properties.get("value").get$ref(), "#/components/schemas/MyJsonPrimitive");
Assert.assertEquals(properties.get("valueWithMixIn").get$ref(), "#/components/schemas/GsonJsonPrimitive");

model = schemas.get("MyJsonPrimitive");
Assert.assertNotNull(model);
Assert.assertTrue(((ComposedSchema)model).getOneOf().size() == 2);
Assert.assertEquals(((ComposedSchema)model).getOneOf().get(0).getType(), "string");
Assert.assertEquals(((ComposedSchema)model).getOneOf().get(1).getType(), "number");

model = schemas.get("GsonJsonPrimitive");
Assert.assertNotNull(model);
Assert.assertTrue(((ComposedSchema)model).getOneOf().size() == 2);
Assert.assertEquals(((ComposedSchema)model).getOneOf().get(0).getType(), "string");
Assert.assertEquals(((ComposedSchema)model).getOneOf().get(1).getType(), "number");
Assert.assertNull(model.getProperties());
}

@Test(description = "read composed schem refs #2616")
public void readArrayComposedSchema_ticket2616() {
Map<String, Schema> schemas = ModelConverters.getInstance().readAll(TestObject2616.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.swagger.v3.core.resolving.resources;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;

@Schema(name = "SomeDTO")
public class TestObjectTicket2900 {

@Schema(implementation = MyJsonPrimitive.class)
public GsonJsonPrimitive value;

@Schema(
description = "Description of value",
oneOf = { String.class, Number.class }
)
public GsonJsonPrimitive valueWithMixIn;


public class GsonJsonPrimitive {
private String foo;
public String getFoo(){return foo;}
}

@Schema(
description = "Description of value",
oneOf = { String.class, Number.class }
)
public class MyJsonPrimitive {
}

public abstract class GsonJsonPrimitiveMixIn {
@JsonIgnore
public abstract String getFoo();
}

}

0 comments on commit 9962469

Please sign in to comment.