|
|
@ -357,8 +357,12 @@ public class SwaggerConfiguration { |
|
|
allOfElement.setProperties(reordered); |
|
|
allOfElement.setProperties(reordered); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} catch (Exception ignored) { |
|
|
} catch (Exception e) { |
|
|
log.trace("Failed to resolve property order for {}", cls.getName(), ignored); |
|
|
log.debug("Failed to resolve property order for {}: {}", cls.getName(), e.getMessage()); |
|
|
|
|
|
// Fallback: at minimum sort alphabetically for determinism
|
|
|
|
|
|
if (hasProps) { |
|
|
|
|
|
schema.setProperties(new LinkedHashMap<>(new TreeMap<>(schema.getProperties()))); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -473,6 +477,12 @@ public class SwaggerConfiguration { |
|
|
.forEach(response -> replaceInlineOneOfInContent(response.getContent(), schemas)); |
|
|
.forEach(response -> replaceInlineOneOfInContent(response.getContent(), schemas)); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Final safety net: ensure all schema properties are in deterministic order.
|
|
|
|
|
|
// The ModelConverter sorts properties during resolution, but springdoc may
|
|
|
|
|
|
// modify schemas afterwards (e.g. polymorphism handling, discriminator injection).
|
|
|
|
|
|
// This pass catches any properties that were added/reordered post-converter.
|
|
|
|
|
|
schemas.values().forEach(this::ensureDeterministicPropertyOrder); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Set JsonNode schema last so model scanning cannot overwrite it
|
|
|
// Set JsonNode schema last so model scanning cannot overwrite it
|
|
|
@ -824,6 +834,28 @@ public class SwaggerConfiguration { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Ensures all properties in a schema (top-level and inside allOf inline elements) |
|
|
|
|
|
* are in deterministic alphabetical order. Acts as a safety net for schemas that |
|
|
|
|
|
* were modified after the ModelConverter's sorting pass (e.g. by springdoc's |
|
|
|
|
|
* polymorphism handling or discriminator injection for interfaces). |
|
|
|
|
|
*/ |
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
|
private void ensureDeterministicPropertyOrder(Schema<?> schema) { |
|
|
|
|
|
if (schema.getProperties() != null && schema.getProperties().size() > 1) { |
|
|
|
|
|
schema.setProperties(new LinkedHashMap<>(new TreeMap<>(schema.getProperties()))); |
|
|
|
|
|
} |
|
|
|
|
|
if (schema.getAllOf() != null) { |
|
|
|
|
|
for (Schema allOfElement : (List<Schema>) schema.getAllOf()) { |
|
|
|
|
|
if (allOfElement.get$ref() == null |
|
|
|
|
|
&& allOfElement.getProperties() != null |
|
|
|
|
|
&& allOfElement.getProperties().size() > 1) { |
|
|
|
|
|
allOfElement.setProperties(new LinkedHashMap<>(new TreeMap<>(allOfElement.getProperties()))); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Returns the JSON property names that are backed by fields declared directly in {@code cls} |
|
|
* Returns the JSON property names that are backed by fields declared directly in {@code cls} |
|
|
* (not inherited from a superclass). Used to distinguish "own" from "inherited" properties |
|
|
* (not inherited from a superclass). Used to distinguish "own" from "inherited" properties |
|
|
|