Skip to content

Commit

Permalink
fix handling of array types as generic type parameters (#2140)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Edgar <[email protected]>
  • Loading branch information
MikeEdgar authored Jan 21, 2025
1 parent 586886c commit 2105ab8
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,7 @@ public Type processType() {
return type;
}

if (type.kind() == Type.Kind.WILDCARD_TYPE) {
type = TypeUtil.resolveWildcard(type.asWildcardType());
}

if (type.kind() == Type.Kind.TYPE_VARIABLE ||
type.kind() == Type.Kind.UNRESOLVED_TYPE_VARIABLE) {
// Resolve type variable to real variable.
type = resolveTypeVariable(schema, type, false);
}

if (TypeUtil.isWrappedType(type)) {
// Unwrap and proceed using the wrapped type
type = TypeUtil.unwrapType(type);
}
type = maybeResolveType(type);

if (isArrayType(type, annotationTarget)) {
return readArrayType(type.asArrayType(), this.schema);
Expand Down Expand Up @@ -150,6 +137,25 @@ public Type processType() {
return type;
}

private Type maybeResolveType(Type type) {
if (type.kind() == Type.Kind.WILDCARD_TYPE) {
type = TypeUtil.resolveWildcard(type.asWildcardType());
}

if (type.kind() == Type.Kind.TYPE_VARIABLE ||
type.kind() == Type.Kind.UNRESOLVED_TYPE_VARIABLE) {
// Resolve type variable to real variable.
type = resolveTypeVariable(schema, type, false);
}

if (TypeUtil.isWrappedType(type)) {
// Unwrap and proceed using the wrapped type
type = TypeUtil.unwrapType(type);
}

return type;
}

/**
* Only allow registration of a type if the annotation target (field or method) that
* refers to the type's class is not annotated with an annotation that alters
Expand Down Expand Up @@ -313,29 +319,10 @@ private Schema resolveParameterizedType(Type valueType, Schema propsSchema) {
typeResolver,
propsSchema);
}
} else if (isArrayType(valueType, null)) {
readArrayType(valueType.asArrayType(), propsSchema);
} else if (index.containsClass(valueType)) {
if (isA(valueType, ENUM_TYPE)) {
DataObjectLogging.logger.processingEnum(type);
propsSchema = SchemaFactory.enumToSchema(context, valueType);
} else {
SchemaSupport.setType(propsSchema, Schema.SchemaType.OBJECT);
}

SchemaRegistry registry = context.getSchemaRegistry();

if (registry.hasSchema(valueType, context.getJsonViews(), typeResolver)) {
if (allowRegistration()) {
propsSchema = registry.lookupRef(valueType, context.getJsonViews());
} else {
pushToStack(valueType, propsSchema);
}
} else {
pushToStack(valueType, propsSchema);
if (allowRegistration()) {
propsSchema = registry.registerReference(valueType, context.getJsonViews(), typeResolver,
propsSchema);
}
}
propsSchema = resolveIndexedParameterizedType(valueType, propsSchema);
}

return propsSchema;
Expand All @@ -357,6 +344,33 @@ private Type resolveTypeVariable(Schema schema, Type fieldType, boolean pushToSt
return resolvedType;
}

private Schema resolveIndexedParameterizedType(Type valueType, Schema propsSchema) {
if (isA(valueType, ENUM_TYPE)) {
DataObjectLogging.logger.processingEnum(type);
propsSchema = SchemaFactory.enumToSchema(context, valueType);
} else {
SchemaSupport.setType(propsSchema, Schema.SchemaType.OBJECT);
}

SchemaRegistry registry = context.getSchemaRegistry();

if (registry.hasSchema(valueType, context.getJsonViews(), typeResolver)) {
if (allowRegistration()) {
propsSchema = registry.lookupRef(valueType, context.getJsonViews());
} else {
pushToStack(valueType, propsSchema);
}
} else {
pushToStack(valueType, propsSchema);
if (allowRegistration()) {
propsSchema = registry.registerReference(valueType, context.getJsonViews(), typeResolver,
propsSchema);
}
}

return propsSchema;
}

private void pushResolvedToStack(Type type, Schema schema) {
Type resolvedType = this.typeResolver.resolve(type);
pushToStack(resolvedType, schema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -888,4 +888,17 @@ class Bean {

assertJsonEquals("components.schemas.primitive-formats.json", Bean.class);
}

@Test
void testMultidimensionalArrayGenericType() throws IOException, JSONException {
@Schema(name = "Bean")
class Bean {
@Schema(description = "Multi-dimensional Array.", examples = "[[[1.23, 1.0903]]]")
List<Double[][]> list;
@Schema(description = "Multi-dimensional Array.", examples = "{ \"data\": [[[1.23, 1.0903]]] }")
Map<String, List<Double[][]>> mapOfLists;
}

assertJsonEquals("components.schemas.multi-array-generic.json", Bean.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"openapi" : "3.1.0",
"components" : {
"schemas" : {
"Bean" : {
"type" : "object",
"properties" : {
"list" : {
"type" : "array",
"items" : {
"type" : "array",
"items" : {
"type" : "array",
"items" : {
"type" : "number",
"format" : "double"
}
}
},
"description" : "Multi-dimensional Array.",
"examples" : [ [ [ [ 1.23, 1.0903 ] ] ] ]
},
"mapOfLists" : {
"type" : "object",
"additionalProperties" : {
"type" : "array",
"items" : {
"type" : "array",
"items" : {
"type" : "array",
"items" : {
"type" : "number",
"format" : "double"
}
}
}
},
"description" : "Multi-dimensional Array.",
"examples" : [ {
"data" : [ [ [ 1.23, 1.0903 ] ] ]
} ]
}
}
}
}
}
}

0 comments on commit 2105ab8

Please sign in to comment.