Browse Source

Fix duplicate OpenAPI schemas for discriminated types

Springdoc creates duplicate schemas with an "Object" suffix when a
discriminated type is resolved through multiple paths. Remove identical
duplicates and replace inline oneOf in additionalProperties.items with
base type $ref for Map<K, List<PolymorphicType>> fields.
pull/15369/head
Viacheslav Klimov 6 months ago
parent
commit
ac600848e6
Failed to extract signature
  1. 33
      application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java

33
application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java

@ -407,6 +407,29 @@ public class SwaggerConfiguration {
}
});
// Springdoc creates duplicate schemas with an "Object" suffix when a discriminated
// type (e.g. EntityExportData) is resolved through multiple paths: once via
// @Schema(implementation=...) and once via generic type resolution (e.g. from
// Map<..., List<EntityExportData<?>>>). The duplicate breaks allOf inheritance
// in generated clients. Remove it only when both schemas are structurally equal.
for (String name : new ArrayList<>(schemas.keySet())) {
if (!name.endsWith("Object")) continue;
String baseName = name.substring(0, name.length() - "Object".length());
Schema<?> baseSchema = schemas.get(baseName);
if (baseSchema == null) continue;
Schema<?> objectSchema = schemas.get(name);
if (!baseSchema.equals(objectSchema)) continue;
schemas.remove(name);
String refToRemove = "#/components/schemas/" + name;
schemas.values().forEach(s -> {
if (s.getAllOf() != null) {
s.getAllOf().removeIf(allOfEntry -> refToRemove.equals(((Schema<?>) allOfEntry).get$ref()));
}
});
log.debug("Removed duplicate schema '{}' (identical to '{}')", name, baseName);
}
// Fix polymorphic properties: replace inline oneOf with base type $ref
schemas.values().forEach(schema -> {
replaceInlineOneOfProperties(schema, schemas);
@ -546,6 +569,16 @@ public class SwaggerConfiguration {
log.debug("Replaced oneOf in additionalProperties with $ref to {} in property {}", baseType, propName);
}
}
// Check if additionalProperties is an array whose items has oneOf (e.g. Map<K, List<PolymorphicType>>)
if (additionalProps.getItems() != null && additionalProps.getItems().getOneOf() != null && !additionalProps.getItems().getOneOf().isEmpty()) {
String baseType = findBaseTypeForOneOf(allSchemas, additionalProps.getItems().getOneOf());
if (baseType != null) {
Schema<?> refSchema = new Schema<>();
refSchema.set$ref("#/components/schemas/" + baseType);
additionalProps.setItems(refSchema);
log.debug("Replaced oneOf in additionalProperties.items with $ref to {} in property {}", baseType, propName);
}
}
}
// If property has oneOf, try to find the base discriminated type

Loading…
Cancel
Save