Repository navigation
feat: ModelCopy.deepCopy, an exact deep copy of OpenAPI models - #5364
Merged
daniel-kmiecik merged 2 commits intoOct 27, 2026
Merged
Conversation
Copying models through a JSON round trip (what AnnotationsUtils.clone, SpecFilter and downstream projects do) isn't a copy: depending on the mapper it loses Schema.getName(), the "example set" flag, the spec version, the concrete model classes (StringSchema becomes Schema, ObjectSchema or JsonSchema), the fields of the other OpenAPI version, null extension values, and the type of example/default values (BigDecimal 1.50 becomes 1.5 or a Double, LocalDate a String, a JsonNode or user object a LinkedHashMap). ModelCopy.deepCopy copies the model graph structurally: models (including subclasses), lists, sets and maps are copied, JsonNodes are deep-copied, other values are shared, and shared references are kept. AnnotationsUtils.clone is unchanged: ModelResolver relies on its normalization. See swagger-api#4991. Signed-off-by: Badr NASS LAHSEN <badr.nasslahsen@gmail.com>
3 tasks
daniel-kmiecik
approved these changes
Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Description
Found while porting springdoc-openapi to Swagger Core 3.0 (feedback in #4991).
Frameworks need to copy models: for example, to customize a copy of the user's
OpenAPIbean for each API group,or to adapt a resolved
Schemawithout changing the one incomponents. Today the only way is a JSON round trip,which is what
AnnotationsUtils.clone,SpecFilterand springdoc-openapi do. That isn't a copy. I measured theround trip on the 3.0.0 branch with a model covering the usual cases:
Json.mapper()round tripJson31.mapper()round tripModelCopy.deepCopyequals(source)StringSchema,ArraySchema)Schema→ObjectSchema)JsonSchemaSchemaSchema.getName()example(null)types,$id)BigDecimalexample1.501.5Double 1.5Double 1.5LocalDate/JsonNode/ user object exampleString/Map/Mapnullextension values¹ After making the 27 base model classes
Serializableon a scratch branch. It fails withNotSerializableExceptionas soon as an example, default, enum or extension value isn'tSerializable, and it wouldadd a serialization contract to every model, so it isn't proposed. An annotation-free Jackson mapper with default
typing was also tested. It keeps most of the above, but fails on user values without a no-arg constructor, turns
Optionalinto its content, and normalizesOffsetDateTimeto UTC.ModelCopy.deepCopy(T)copies the graph structurally:io.swagger.v3.oas.models), lists, sets and maps are copied;JsonNodes are deep-copied;It's one self-contained class, with no changes to the models.
AnnotationsUtils.cloneis intentionally unchanged. I tried delegating it: 5 tests fail, becauseModelResolverrelies on the round trip's normalization, for example to
JsonSchemawith OpenAPI 3.1. Swagger Core can adoptModelCopyinternally later, case by case.Fixes:
Type of Change
Checklist
ModelCopyTest