Skip to content

Commit 5ef12d2

Browse files
committed
fix additional properties handling in 3.1 spec
1 parent ddb15d4 commit 5ef12d2

5 files changed

Lines changed: 182 additions & 3 deletions

File tree

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -723,15 +723,17 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
723723
if (skipNormalization(schema, visitedSchemas)) {
724724
return schema;
725725
}
726+
727+
if (ModelUtils.isNullTypeSchema(openAPI, schema)) {
728+
return schema;
729+
}
730+
726731
markSchemaAsVisited(schema, visitedSchemas);
727732

728733
if (ModelUtils.isArraySchema(schema)) { // array
729734
Schema result = normalizeArraySchema(schema);
730735
normalizeSchema(result.getItems(), visitedSchemas);
731736
return result;
732-
} else if (schema.getAdditionalProperties() instanceof Schema) { // map
733-
normalizeMapSchema(schema);
734-
normalizeSchema((Schema) schema.getAdditionalProperties(), visitedSchemas);
735737
} else if (ModelUtils.isOneOf(schema)) { // oneOf
736738
return normalizeOneOf(schema, visitedSchemas);
737739
} else if (ModelUtils.isAnyOf(schema)) { // anyOf
@@ -768,6 +770,9 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
768770
return schema;
769771
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
770772
normalizeProperties(schema.getProperties(), visitedSchemas);
773+
} else if (schema.getAdditionalProperties() instanceof Schema) { // map
774+
normalizeMapSchema(schema);
775+
normalizeSchema((Schema) schema.getAdditionalProperties(), visitedSchemas);
771776
} else if (schema instanceof BooleanSchema) {
772777
normalizeBooleanSchema(schema, visitedSchemas);
773778
} else if (schema instanceof IntegerSchema) {
@@ -1011,6 +1016,7 @@ protected Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
10111016
if (schema.getAnyOf() == null) {
10121017
return schema;
10131018
}
1019+
10141020
for (int i = 0; i < schema.getAnyOf().size(); i++) {
10151021
// normalize anyOf sub schemas one by one
10161022
Object item = schema.getAnyOf().get(i);

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,11 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() {
953953
Schema schema21 = openAPI.getComponents().getSchemas().get("SingleAnyOfTest");
954954
assertEquals(schema21.getAnyOf().size(), 1);
955955

956+
Schema schema23 = openAPI.getComponents().getSchemas().get("PropertiesWithAnyOf");
957+
assertEquals(((Schema) schema23.getProperties().get("anyof_nullable_string")).getAnyOf().size(), 2);
958+
assertEquals(((Schema) schema23.getProperties().get("anyof_nullable_number")).getAnyOf().size(), 2);
959+
960+
// start the normalization
956961
Map<String, String> options = new HashMap<>();
957962
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
958963
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
@@ -1007,6 +1012,14 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() {
10071012
assertEquals(schema22.getAnyOf(), null);
10081013
assertEquals(schema22.getTypes(), Set.of("string"));
10091014
assertEquals(schema22.getEnum().size(), 2);
1015+
1016+
Schema schema24 = openAPI.getComponents().getSchemas().get("PropertiesWithAnyOf");
1017+
assertEquals(((Schema) schema24.getProperties().get("anyof_nullable_string")).getAnyOf(), null);
1018+
assertEquals(((Schema) schema24.getProperties().get("anyof_nullable_string")).getNullable(), true);
1019+
assertEquals(((Schema) schema24.getProperties().get("anyof_nullable_string")).getTypes().size(), 1);
1020+
assertEquals(((Schema) schema24.getProperties().get("anyof_nullable_number")).getAnyOf(), null);
1021+
assertEquals(((Schema) schema24.getProperties().get("anyof_nullable_number")).getNullable(), true);
1022+
assertEquals(((Schema) schema24.getProperties().get("anyof_nullable_number")).getTypes().size(), 1);
10101023
}
10111024

10121025
@Test

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,47 @@ public void isNullTypeSchemaTest() {
623623
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
624624
}
625625

626+
@Test
627+
public void isNullTypeSchemaTestWith31Spec() {
628+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/null_schema_test.yaml");
629+
Map<String, String> options = new HashMap<>();
630+
Schema schema = openAPI.getComponents().getSchemas().get("AnyOfStringArrayOfString");
631+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
632+
633+
schema = openAPI.getComponents().getSchemas().get("IntegerRef");
634+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
635+
636+
schema = openAPI.getComponents().getSchemas().get("OneOfAnyType");
637+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
638+
639+
schema = openAPI.getComponents().getSchemas().get("AnyOfAnyType");
640+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
641+
642+
schema = openAPI.getComponents().getSchemas().get("Parent");
643+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
644+
// the dummy property is a ref to integer
645+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getProperties().get("dummy")));
646+
647+
schema = openAPI.getComponents().getSchemas().get("AnyOfTest");
648+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
649+
// first element (getAnyOf().get(0)) is a string. no need to test
650+
assertTrue(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getAnyOf().get(1)));
651+
assertTrue(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getAnyOf().get(2)));
652+
assertTrue(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getAnyOf().get(3)));
653+
654+
schema = openAPI.getComponents().getSchemas().get("OneOfRef");
655+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
656+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getOneOf().get(0)));
657+
658+
schema = openAPI.getComponents().getSchemas().get("OneOfMultiRef");
659+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
660+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getOneOf().get(0)));
661+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getOneOf().get(1)));
662+
663+
schema = openAPI.getComponents().getSchemas().get("JustDescription");
664+
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
665+
}
666+
626667
@Test
627668
public void isUnsupportedSchemaTest() {
628669
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/unsupported_schema_test.yaml");
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
openapi: 3.1.0
2+
info:
3+
version: 1.0.0
4+
title: Example
5+
license:
6+
name: MIT
7+
servers:
8+
- url: http://api.example.xyz/v1
9+
paths:
10+
/person/display/{personId}:
11+
get:
12+
parameters:
13+
- name: personId
14+
in: path
15+
required: true
16+
description: The id of the person to retrieve
17+
schema:
18+
type: string
19+
operationId: list
20+
responses:
21+
'200':
22+
description: OK
23+
content:
24+
application/json:
25+
schema:
26+
$ref: "#/components/schemas/AnyOfTest"
27+
components:
28+
schemas:
29+
AnyOfTest:
30+
description: to test anyOf
31+
anyOf:
32+
- type: string
33+
- type: 'null'
34+
- type: null
35+
- $ref: null
36+
OneOfTest:
37+
description: to test oneOf
38+
oneOf:
39+
- type: integer
40+
- type: 'null'
41+
- type: null
42+
- $ref: null
43+
OneOfTest2:
44+
description: to test oneOf
45+
oneOf:
46+
- type: string
47+
- type: 'null'
48+
OneOfNullableTest:
49+
description: to test oneOf nullable
50+
oneOf:
51+
- type: integer
52+
- type: string
53+
- $ref: null
54+
Parent:
55+
type: object
56+
properties:
57+
dummy:
58+
$ref: '#/components/schemas/IntegerRef'
59+
string_ref:
60+
anyOf:
61+
- $ref: '#/components/schemas/StringRef'
62+
AnyOfStringArrayOfString:
63+
anyOf:
64+
- type: string
65+
- type: array
66+
items:
67+
type: string
68+
AnyOfAnyType:
69+
anyOf:
70+
- type: boolean
71+
- type: array
72+
items: {}
73+
- type: object
74+
- type: string
75+
- type: number
76+
- type: integer
77+
AnyOfAnyTypeWithRef:
78+
anyOf:
79+
- type: boolean
80+
- type: array
81+
items: { }
82+
- type: object
83+
- type: string
84+
- type: number
85+
- $ref: '#/components/schemas/IntegerRef'
86+
IntegerRef:
87+
type: integer
88+
StringRef:
89+
type: string
90+
OneOfAnyType:
91+
oneOf:
92+
- type: object
93+
- type: boolean
94+
- type: number
95+
- type: string
96+
- type: integer
97+
- type: array
98+
items: {}
99+
OneOfRef:
100+
oneOf:
101+
- $ref: '#/components/schemas/IntegerRef'
102+
OneOfMultiRef:
103+
oneOf:
104+
- $ref: '#/components/schemas/IntegerRef'
105+
- $ref: '#/components/schemas/StringRef'
106+
JustDescription:
107+
description: A schema with just description

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ components:
7777
oneOf:
7878
- $ref: '#/components/schemas/Number'
7979
- $ref: '#/components/schemas/Number2'
80+
PropertiesWithAnyOf:
81+
additionalProperties: false
82+
type: object
83+
properties:
84+
anyof_nullable_string:
85+
anyOf:
86+
- type: string
87+
- type: null
88+
anyof_nullable_number:
89+
anyOf:
90+
- type: number
91+
- type: null
8092
Number:
8193
enum:
8294
- one

0 commit comments

Comments
 (0)