Skip to content

Commit 5f5f679

Browse files
committed
Convert a ComposedSchema to a Schema if there is no oneOf/allOf/anyOf
-> avoid side effects with bugs in InlineModelResolver
1 parent 0facdf7 commit 5f5f679

2 files changed

Lines changed: 102 additions & 7 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
747747
if (ModelUtils.isNullTypeSchema(openAPI, schema)) {
748748
return schema;
749749
}
750-
750+
schema = decomposeSchema(schema);
751751
markSchemaAsVisited(schema, visitedSchemas);
752752

753753
processNormalizeOtherThanObjectWithProperties(schema);
@@ -1062,8 +1062,6 @@ protected Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
10621062
// simplify first as the schema may no longer be a oneOf after processing the rule below
10631063
schema = processSimplifyOneOf(schema);
10641064

1065-
schema = processReplaceOneOfByMapping(schema);
1066-
10671065
// if it's still a oneOf, loop through the sub-schemas
10681066
if (schema.getOneOf() != null) {
10691067
for (int i = 0; i < schema.getOneOf().size(); i++) {
@@ -1080,19 +1078,20 @@ protected Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
10801078
// update sub-schema with the updated schema
10811079
schema.getOneOf().set(i, normalizeSchema((Schema) item, visitedSchemas));
10821080
}
1081+
schema = processReplaceOneOfByMapping(schema);
10831082
} else {
10841083
// normalize it as it's no longer an oneOf
10851084
schema = normalizeSchema(schema, visitedSchemas);
10861085
}
1087-
1086+
schema = decomposeSchema(schema);
10881087
return schema;
10891088
}
10901089

10911090
protected Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
10921091
//transform anyOf into enums if needed
10931092
schema = processSimplifyAnyOfEnum(schema);
10941093
if (schema.getAnyOf() == null) {
1095-
return schema;
1094+
return decomposeSchema(schema);
10961095
}
10971096

10981097
for (int i = 0; i < schema.getAnyOf().size(); i++) {
@@ -1620,21 +1619,34 @@ protected Schema processReplaceOneOfByMapping(Schema schema) {
16201619

16211620
}
16221621
// remove oneOf and only keep the new discriminator mapping
1623-
schema.setOneOf(null);
1622+
schema.oneOf(null);
16241623
} else if (discriminator.getPropertyName() == null) {
16251624
LOGGER.warn("Missing property name in discriminator");
16261625
} else if (discriminator.getMapping() != null && discriminator.getMapping().size() != schema.getOneOf().size()) {
16271626
LOGGER.warn("Discriminator mapping size " + discriminator.getMapping().size() + " mismatch with oneOf size " + schema.getOneOf().size());
16281627
} else {
16291628
// remove oneOf and only keep the discriminator mapping
16301629
LOGGER.info("Removing oneOf, discriminator mapping takes precedences on OneOfs");
1631-
schema.setOneOf(null);
1630+
schema.oneOf(null);
16321631
}
16331632
}
16341633

16351634
return schema;
16361635
}
16371636

1637+
/**
1638+
* Replace a ComposeSchema into a Simple Schema if no OneOf/AnyOf/AllOf.
1639+
*
1640+
* This allows side effects with ModelUtils.isComposedSchema() that returns true for a ComposedSchema.
1641+
* For example the InlineModelResolver does not inline properties of a ComposedSchema (a bug to be fixed in another PR)
1642+
*/
1643+
private Schema decomposeSchema(Schema schema) {
1644+
if (schema instanceof ComposedSchema && schema.getOneOf() == null && schema.getAnyOf() == null && schema.getAllOf() == null) {
1645+
schema = ModelUtils.shallowCopy(schema, new Schema());
1646+
}
1647+
return schema;
1648+
}
1649+
16381650
private boolean isInlineSchema(Schema schema) {
16391651
if (openAPI.getComponents()!=null && openAPI.getComponents().getSchemas()!=null) {
16401652
int identity = System.identityHashCode(schema);

modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.swagger.v3.oas.models.OpenAPI;
2626
import io.swagger.v3.oas.models.Operation;
2727
import io.swagger.v3.oas.models.PathItem;
28+
import io.swagger.v3.oas.models.SpecVersion;
2829
import io.swagger.v3.oas.models.callbacks.Callback;
2930
import io.swagger.v3.oas.models.headers.Header;
3031
import io.swagger.v3.oas.models.media.*;
@@ -2270,6 +2271,88 @@ public static boolean isParent(Schema schema) {
22702271
return false;
22712272
}
22722273

2274+
/**
2275+
* copy all the fields from the origin schema to the destination schema.
2276+
* @param schema original schema
2277+
* @param dest the destination schema
2278+
* @return dest
2279+
*/
2280+
2281+
public static Schema shallowCopy(Schema schema, Schema dest) {
2282+
// cloneSchema does not work because it does conversions for some attributes (enums, default...)
2283+
// the intermediate JSON can convert between integer and BigInteger for example.
2284+
// so copy all the fields individually
2285+
dest.setDefault(schema.getDefault());
2286+
dest.setName(schema.getName());
2287+
dest.setTitle(schema.getTitle());
2288+
dest.setMultipleOf(schema.getMultipleOf());
2289+
dest.setMaximum(schema.getMaximum());
2290+
dest.setExclusiveMaximum(schema.getExclusiveMaximum());
2291+
dest.setMinimum(schema.getMinimum());
2292+
dest.setExclusiveMinimum(schema.getExclusiveMinimum());
2293+
dest.setMaxLength(schema.getMaxLength());
2294+
dest.setPattern(schema.getPattern());
2295+
dest.setMaxItems(schema.getMaxItems());
2296+
dest.setMinItems(schema.getMinItems());
2297+
dest.setUnevaluatedItems(schema.getUnevaluatedItems());
2298+
dest.setMaxProperties(schema.getMaxProperties());
2299+
dest.setMinProperties(schema.getMinProperties());
2300+
dest.setRequired(schema.getRequired());
2301+
dest.setType(schema.getType());
2302+
dest.setNot(schema.getNot());
2303+
dest.setProperties(schema.getProperties());
2304+
dest.setDescription(schema.getDescription());
2305+
dest.setFormat(schema.getFormat());
2306+
dest.set$ref(schema.get$ref());
2307+
dest.setNullable(schema.getNullable());
2308+
dest.setReadOnly(schema.getReadOnly());
2309+
dest.setWriteOnly(schema.getWriteOnly());
2310+
dest.setExample(schema.getExample());
2311+
dest.setExternalDocs(schema.getExternalDocs());
2312+
dest.setDeprecated(schema.getDeprecated());
2313+
dest.setXml(schema.getXml());
2314+
dest.setExtensions(schema.getExtensions());
2315+
dest.setEnum(schema.getEnum());
2316+
dest.setDiscriminator(schema.getDiscriminator());
2317+
dest.setExampleSetFlag(schema.getExampleSetFlag());
2318+
dest.setPrefixItems(schema.getPrefixItems());
2319+
dest.setAllOf(schema.getAllOf());
2320+
dest.setAnyOf(schema.getAnyOf());
2321+
dest.setOneOf(schema.getOneOf());
2322+
dest.setItems(schema.getItems());
2323+
dest.setConst(schema.getConst());
2324+
dest.setSpecVersion(schema.getSpecVersion());
2325+
dest.setPatternProperties(schema.getPatternProperties());
2326+
dest.setExclusiveMaximumValue(schema.getExclusiveMaximumValue());
2327+
dest.setExclusiveMinimumValue(schema.getExclusiveMinimumValue());
2328+
dest.setContains(schema.getContains());
2329+
dest.set$id(schema.get$id());
2330+
dest.set$schema(schema.get$schema());
2331+
dest.set$anchor(schema.get$anchor());
2332+
dest.set$vocabulary(schema.get$vocabulary());
2333+
dest.set$dynamicAnchor(schema.get$dynamicAnchor());
2334+
dest.set$dynamicRef(schema.get$dynamicRef());
2335+
dest.setContentEncoding(schema.getContentEncoding());
2336+
dest.setContentMediaType(schema.getContentMediaType());
2337+
dest.setPropertyNames(schema.getPropertyNames());
2338+
dest.setUnevaluatedProperties(schema.getUnevaluatedProperties());
2339+
dest.setMaxContains(schema.getMaxContains());
2340+
dest.setMinContains(schema.getMinContains());
2341+
dest.setAdditionalItems(schema.getAdditionalItems());
2342+
dest.setUnevaluatedItems(schema.getUnevaluatedItems());
2343+
dest.setIf(schema.getIf());
2344+
dest.setElse(schema.getElse());
2345+
dest.setThen(schema.getThen());
2346+
dest.setDependentSchemas(schema.getDependentSchemas());
2347+
dest.setDependentRequired(schema.getDependentRequired());
2348+
dest.set$comment(schema.get$comment());
2349+
dest.setExamples(schema.getExamples());
2350+
dest.setBooleanSchemaValue(schema.getBooleanSchemaValue());
2351+
dest.setJsonSchema(schema.getJsonSchema());
2352+
dest.setJsonSchemaImpl(schema.getJsonSchemaImpl());
2353+
return dest;
2354+
}
2355+
22732356
public static Schema cloneSchema(Schema schema, boolean openapi31) {
22742357
if (openapi31) {
22752358
return AnnotationsUtils.clone(schema, openapi31);

0 commit comments

Comments
 (0)