Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ static <T> List<T> wrapInList(T value) {
* @param schemaReferenceSupported
*/
static Schema readClassSchema(final AnnotationScannerContext context, Type type, boolean schemaReferenceSupported) {
if (type == null) {
if (type == null || TypeUtil.isVoid(type)) {
return null;
}
Schema schema;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ private void depthFirstGraphSearch() {
continue;
}

if (!hasNonNullType(currentSchema)) {
if (!hasNonNullType(currentSchema)
&& !isImplementationVoid(currentTarget, currentClass)) {
// If not schema has yet been set, consider this an "object"
SchemaSupport.setType(currentSchema, Schema.SchemaType.OBJECT);
} else if (allowRegistration) {
Expand All @@ -288,6 +289,31 @@ private void depthFirstGraphSearch() {
}
}

/**
* Determine if the {@code implementation} for the schema has been voided via an annotation,
* either on the target being scanned or the class itself
*
* @param target annotated target, possible null
* @param clazz target class that may be hosting a {@literal @}Schema annotation
*/
private boolean isImplementationVoid(AnnotationTarget target, ClassInfo clazz) {
for (AnnotationTarget t : Arrays.asList(target, clazz)) {
Type type = context.annotations()
.getAnnotationValue(t, SchemaConstant.DOTNAME_SCHEMA,
SchemaConstant.PROP_IMPLEMENTATION);

if (TypeUtil.isVoid(type)) {
return true;
}

if (type != null) {
return false;
}
}

return false;
}

private void maybeRegisterSchema(Type currentType, Schema currentSchema, Schema entrySchema) {
Schema ref = SchemaFactory.schemaRegistration(context, currentType, currentSchema);
Schema.SchemaType type = SchemaSupport.getNonNullType(currentSchema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public class TypeUtil {
// https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#dataTypeFormat
static {
TYPE_MAP.put(DOTNAME_OBJECT, ANY);
TYPE_MAP.put(DOTNAME_VOID, ANY);

// String
TYPE_MAP.put(DotName.createSimple(String.class.getName()), STRING_FORMAT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1084,4 +1084,31 @@ class DataList extends GenericListRoot<Bean> {
assertJsonEquals("components.schemas.resolved-mapped-generic-ptype.json",
Bean.class, GenericRoot.class, GenericListRoot.class, Data.class, DataList.class);
}

static final class TestVoidImplementationNoType {
@Schema(oneOf = { Implementation.class, String.class }, implementation = Void.class)
interface IFace1 {
}

interface IFace2 {
}

@Schema(additionalProperties = Schema.False.class)
static class Implementation implements IFace1 {
@Schema(required = true, description = "Identifier")
String id;
@Schema(defaultValue = "1", minimum = "1", description = "Sequence of this implemenatation instance")
long sequence;
@Schema(oneOf = { Implementation.class, String.class }, implementation = Void.class)
IFace2 oneOfIface2;
@Schema(implementation = String.class)
IFace2 stringIface2;
}
}

@Test
void testVoidImplementationNoType() throws IOException, JSONException {
assertJsonEquals("components.schemas.void-implementation-no-type.json",
TestVoidImplementationNoType.IFace1.class, TestVoidImplementationNoType.Implementation.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"openapi" : "3.1.0",
"components" : {
"schemas" : {
"IFace1" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/Implementation"
}, {
"type" : "string"
} ]
},
"Implementation" : {
"additionalProperties" : false,
"type" : "object",
"required" : [ "id" ],
"properties" : {
"id" : {
"type" : "string",
"description" : "Identifier"
},
"sequence" : {
"type" : "integer",
"format" : "int64",
"minimum" : 1,
"description" : "Sequence of this implemenatation instance",
"default" : 1
},
"oneOfIface2" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/Implementation"
}, {
"type" : "string"
} ]
},
"stringIface2" : {
"type" : "string"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,6 @@
}
},
"voidField": {
"type": "object"
},
"writeOnlyInteger": {
"format": "int32",
Expand Down