Skip to content

Commit 2111713

Browse files
authored
Fix anyOf/oneOf normalization for 3.1 spec (#19758)
* fix anyOf/oneOf normalization for 3.1 spec * update samples
1 parent fad33df commit 2111713

File tree

6 files changed

+68
-9
lines changed

6 files changed

+68
-9
lines changed

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
516516
return schema;
517517
}
518518

519-
if ((visitedSchemas.contains(schema))) {
519+
if (visitedSchemas.contains(schema)) {
520520
return schema; // skip due to circular reference
521521
} else {
522522
visitedSchemas.add(schema);
@@ -535,7 +535,6 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
535535
return normalizeAnyOf(schema, visitedSchemas);
536536
} else if (ModelUtils.isAllOfWithProperties(schema)) { // allOf with properties
537537
schema = normalizeAllOfWithProperties(schema, visitedSchemas);
538-
normalizeSchema(schema, visitedSchemas);
539538
} else if (ModelUtils.isAllOf(schema)) { // allOf
540539
return normalizeAllOf(schema, visitedSchemas);
541540
} else if (ModelUtils.isComposedSchema(schema)) { // composed schema
@@ -643,15 +642,19 @@ private Schema normalizeAllOfWithProperties(Schema schema, Set<Schema> visitedSc
643642
}
644643

645644
private Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
646-
for (Object item : schema.getOneOf()) {
645+
for (int i = 0; i < schema.getOneOf().size(); i++) {
646+
// normalize oneOf sub schemas one by one
647+
Object item = schema.getOneOf().get(i);
648+
647649
if (item == null) {
648650
continue;
649651
}
650652
if (!(item instanceof Schema)) {
651653
throw new RuntimeException("Error! oneOf schema is not of the type Schema: " + item);
652654
}
653-
// normalize oenOf sub schemas one by one
654-
normalizeSchema((Schema) item, visitedSchemas);
655+
656+
// update sub-schema with the updated schema
657+
schema.getOneOf().set(i, normalizeSchema((Schema) item, visitedSchemas));
655658
}
656659
// process rules here
657660
schema = processSimplifyOneOf(schema);
@@ -660,16 +663,20 @@ private Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
660663
}
661664

662665
private Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
663-
for (Object item : schema.getAnyOf()) {
666+
for (int i = 0; i < schema.getAnyOf().size(); i++) {
667+
// normalize anyOf sub schemas one by one
668+
Object item = schema.getAnyOf().get(i);
669+
664670
if (item == null) {
665671
continue;
666672
}
667673

668674
if (!(item instanceof Schema)) {
669675
throw new RuntimeException("Error! anyOf schema is not of the type Schema: " + item);
670676
}
671-
// normalize anyOf sub schemas one by one
672-
normalizeSchema((Schema) item, visitedSchemas);
677+
678+
// update sub-schema with the updated schema
679+
schema.getAnyOf().set(i, normalizeSchema((Schema) item, visitedSchemas));
673680
}
674681

675682
// process rules here

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,9 @@ public static Schema<?> getSchemaItems(Schema schema) {
600600
Schema<?> items = schema.getItems();
601601
if (items == null) {
602602
if (schema instanceof JsonSchema) { // 3.1 spec
603-
// do nothing as the schema may contain prefixItems only
603+
// set the items to a new schema (any type)
604+
items = new Schema<>();
605+
schema.setItems(items);
604606
} else { // 3.0 spec, default to string
605607
LOGGER.error("Undefined array inner type for `{}`. Default to String.", schema.getName());
606608
items = new StringSchema().description("TODO default missing array inner type to string");

modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,16 @@ public void testOpenAPINormalizerProcessingArraySchema31Spec() {
605605
assertNotEquals(((Schema) schema7.getProperties().get("with_prefixitems")).getPrefixItems(), null);
606606
assertEquals(((Schema) schema7.getProperties().get("without_items")).getItems(), null);
607607

608+
Schema schema9 = openAPI.getComponents().getSchemas().get("AnyOfArrayWithPrefixItems");
609+
assertEquals(((Schema) schema9.getAnyOf().get(0)).getItems(), null);
610+
assertNotEquals(((Schema) schema9.getAnyOf().get(0)).getPrefixItems(), null);
611+
assertEquals(((Schema) schema9.getAnyOf().get(1)).getItems(), null);
612+
613+
Schema schema11 = openAPI.getComponents().getSchemas().get("OneOfArrayWithPrefixItems");
614+
assertEquals(((Schema) schema11.getOneOf().get(0)).getItems(), null);
615+
assertNotEquals(((Schema) schema11.getOneOf().get(0)).getPrefixItems(), null);
616+
assertEquals(((Schema) schema11.getOneOf().get(1)).getItems(), null);
617+
608618
Map<String, String> inputRules = Map.of("NORMALIZE_31SPEC", "true");
609619
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, inputRules);
610620
openAPINormalizer.normalize();
@@ -632,6 +642,16 @@ public void testOpenAPINormalizerProcessingArraySchema31Spec() {
632642
assertNotEquals(((Schema) schema8.getProperties().get("with_prefixitems")).getItems(), null);
633643
assertEquals(((Schema) schema8.getProperties().get("with_prefixitems")).getPrefixItems(), null);
634644
assertNotEquals(((Schema) schema8.getProperties().get("without_items")).getItems(), null);
645+
646+
Schema schema10 = openAPI.getComponents().getSchemas().get("AnyOfArrayWithPrefixItems");
647+
assertNotEquals(((Schema) schema10.getAnyOf().get(0)).getItems(), null);
648+
assertEquals(((Schema) schema10.getAnyOf().get(0)).getPrefixItems(), null);
649+
assertNotEquals(((Schema) schema10.getAnyOf().get(1)).getItems(), null);
650+
651+
Schema schema12 = openAPI.getComponents().getSchemas().get("OneOfArrayWithPrefixItems");
652+
assertNotEquals(((Schema) schema12.getOneOf().get(0)).getItems(), null);
653+
assertEquals(((Schema) schema12.getOneOf().get(0)).getPrefixItems(), null);
654+
assertNotEquals(((Schema) schema12.getOneOf().get(1)).getItems(), null);
635655
}
636656

637657
@Test

modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,12 @@ public void testCloneDateTimeSchemaWithExample() {
461461
Assert.assertEquals(deepCopy, schema);
462462
Assert.assertNotSame(deepCopy, schema);
463463
}
464+
465+
@Test
466+
public void testGetSchemaItemsWith31Spec() {
467+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/issue_18291.yaml");
468+
Schema arrayWithPrefixItems = ModelUtils.getSchema(openAPI, "ArrayWithPrefixItems");
469+
Assert.assertNotNull(ModelUtils.getSchemaItems((Schema) arrayWithPrefixItems.getProperties().get("with_prefixitems")));
470+
Assert.assertNotNull(ModelUtils.getSchemaItems((Schema) arrayWithPrefixItems.getProperties().get("without_items")));
471+
}
464472
}

modules/openapi-generator/src/test/resources/3_1/issue_18291.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,23 @@ components:
4747
minItems: 2
4848
without_items:
4949
type: array
50+
AnyOfArrayWithPrefixItems:
51+
anyOf:
52+
- type: array
53+
prefixItems:
54+
- type: number
55+
title: Longitude
56+
- type: number
57+
title: Latitude
58+
maxItems: 2
59+
minItems: 2
60+
- type: array
61+
OneOfArrayWithPrefixItems:
62+
oneOf:
63+
- type: array
64+
prefixItems:
65+
- type: integer
66+
- type: integer
67+
maxItems: 3
68+
minItems: 3
69+
- type: array

samples/client/petstore/java/okhttp-gson-3.1/api/openapi.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,7 @@ paths:
815815
items:
816816
$ref: '#/components/schemas/myObject'
817817
nullable: true
818+
type: array
818819
description: ""
819820
tags:
820821
- fake
@@ -1185,6 +1186,7 @@ components:
11851186
- type: string
11861187
- items:
11871188
type: string
1189+
type: array
11881190
securitySchemes:
11891191
petstore_auth:
11901192
flows:

0 commit comments

Comments
 (0)