forked from loafle/openapi-generator-original
[normalizer] bug fixes (isNullTypeSchema, handling of primitive types with oneOf) (#19781)
* better handling of primivitype type with oneOf * fix null check, add tests * add check for properties
This commit is contained in:
parent
8e10dd7be7
commit
ad6c2dd2b7
@ -642,23 +642,30 @@ public class OpenAPINormalizer {
|
||||
}
|
||||
|
||||
private Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
|
||||
for (int i = 0; i < schema.getOneOf().size(); i++) {
|
||||
// normalize oneOf sub schemas one by one
|
||||
Object item = schema.getOneOf().get(i);
|
||||
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
if (!(item instanceof Schema)) {
|
||||
throw new RuntimeException("Error! oneOf schema is not of the type Schema: " + item);
|
||||
}
|
||||
|
||||
// update sub-schema with the updated schema
|
||||
schema.getOneOf().set(i, normalizeSchema((Schema) item, visitedSchemas));
|
||||
}
|
||||
// process rules here
|
||||
// simplify first as the schema may no longer be a oneOf after processing the rule below
|
||||
schema = processSimplifyOneOf(schema);
|
||||
|
||||
// if it's still a oneOf, loop through the sub-schemas
|
||||
if (schema.getOneOf() != null) {
|
||||
for (int i = 0; i < schema.getOneOf().size(); i++) {
|
||||
// normalize oneOf sub schemas one by one
|
||||
Object item = schema.getOneOf().get(i);
|
||||
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
if (!(item instanceof Schema)) {
|
||||
throw new RuntimeException("Error! oneOf schema is not of the type Schema: " + item);
|
||||
}
|
||||
|
||||
// update sub-schema with the updated schema
|
||||
schema.getOneOf().set(i, normalizeSchema((Schema) item, visitedSchemas));
|
||||
}
|
||||
} else {
|
||||
// normalize it as it's no longer an oneOf
|
||||
schema = normalizeSchema(schema, visitedSchemas);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
@ -683,7 +690,7 @@ public class OpenAPINormalizer {
|
||||
schema = processSimplifyAnyOf(schema);
|
||||
|
||||
// last rule to process as the schema may become String schema (not "anyOf") after the completion
|
||||
return processSimplifyAnyOfStringAndEnumString(schema);
|
||||
return normalizeSchema(processSimplifyAnyOfStringAndEnumString(schema), visitedSchemas);
|
||||
}
|
||||
|
||||
private Schema normalizeComplexComposedSchema(Schema schema, Set<Schema> visitedSchemas) {
|
||||
@ -694,7 +701,7 @@ public class OpenAPINormalizer {
|
||||
|
||||
processRemoveAnyOfOneOfAndKeepPropertiesOnly(schema);
|
||||
|
||||
return schema;
|
||||
return normalizeSchema(schema, visitedSchemas);
|
||||
}
|
||||
|
||||
// ===================== a list of rules =====================
|
||||
@ -893,21 +900,40 @@ public class OpenAPINormalizer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the schema is of type 'null'
|
||||
* Check if the schema is of type 'null' or schema itself is pointing to null
|
||||
* <p>
|
||||
* Return true if the schema's type is 'null' or not specified
|
||||
*
|
||||
* @param schema Schema
|
||||
* @param openAPI OpenAPI
|
||||
*
|
||||
* @return true if schema is null type
|
||||
*/
|
||||
public boolean isNullTypeSchema(Schema schema) {
|
||||
public boolean isNullTypeSchema(OpenAPI openAPI, Schema schema) {
|
||||
if (schema == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// dereference the schema
|
||||
schema = ModelUtils.getReferencedSchema(openAPI, schema);
|
||||
|
||||
// allOf/anyOf/oneOf
|
||||
if (ModelUtils.hasAllOf(schema) || ModelUtils.hasOneOf(schema) || ModelUtils.hasAnyOf(schema)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// schema with properties
|
||||
if (schema.getProperties() != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert referenced enum of null only to `nullable:true`
|
||||
if (schema.getEnum() != null && schema.getEnum().size() == 1) {
|
||||
if ("null".equals(String.valueOf(schema.getEnum().get(0)))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (schema.getTypes() != null && !schema.getTypes().isEmpty()) {
|
||||
// 3.1 spec
|
||||
if (schema.getTypes().size() == 1) { // 1 type only
|
||||
@ -933,14 +959,6 @@ public class OpenAPINormalizer {
|
||||
}
|
||||
}
|
||||
|
||||
// convert referenced enum of null only to `nullable:true`
|
||||
Schema referencedSchema = ModelUtils.getReferencedSchema(openAPI, schema);
|
||||
if (referencedSchema.getEnum() != null && referencedSchema.getEnum().size() == 1) {
|
||||
if ("null".equals(String.valueOf(referencedSchema.getEnum().get(0)))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -986,7 +1004,7 @@ public class OpenAPINormalizer {
|
||||
}
|
||||
}
|
||||
|
||||
if (oneOfSchemas.removeIf(oneOf -> isNullTypeSchema(oneOf))) {
|
||||
if (oneOfSchemas.removeIf(oneOf -> isNullTypeSchema(openAPI, oneOf))) {
|
||||
schema.setNullable(true);
|
||||
|
||||
// if only one element left, simplify to just the element (schema)
|
||||
@ -997,6 +1015,11 @@ public class OpenAPINormalizer {
|
||||
return (Schema) oneOfSchemas.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ModelUtils.isIntegerSchema(schema) || ModelUtils.isNumberSchema(schema) || ModelUtils.isStringSchema(schema)) {
|
||||
// TODO convert oneOf const to enum
|
||||
schema.setOneOf(null);
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
@ -1117,7 +1140,7 @@ public class OpenAPINormalizer {
|
||||
}
|
||||
}
|
||||
|
||||
if (anyOfSchemas.removeIf(anyOf -> isNullTypeSchema(anyOf))) {
|
||||
if (anyOfSchemas.removeIf(anyOf -> isNullTypeSchema(openAPI, anyOf))) {
|
||||
schema.setNullable(true);
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ public class OpenAPINormalizerTest {
|
||||
Map<String, String> options = new HashMap<>();
|
||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||
Schema schema = openAPI.getComponents().getSchemas().get("AnyOfStringArrayOfString");
|
||||
assertFalse(openAPINormalizer.isNullTypeSchema(schema));
|
||||
assertFalse(openAPINormalizer.isNullTypeSchema(openAPI, schema));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -705,6 +705,12 @@ public class OpenAPINormalizerTest {
|
||||
Schema schema13 = openAPI.getComponents().getSchemas().get("OneOfAnyType");
|
||||
assertEquals(schema13.getOneOf().size(), 6);
|
||||
|
||||
Schema schema15 = openAPI.getComponents().getSchemas().get("TypeIntegerWithOneOf");
|
||||
assertEquals(schema15.getOneOf().size(), 3);
|
||||
|
||||
Schema schema17 = openAPI.getComponents().getSchemas().get("OneOfNullAndRef3");
|
||||
assertEquals(schema17.getOneOf().size(), 2);
|
||||
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
|
||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||
@ -742,5 +748,14 @@ public class OpenAPINormalizerTest {
|
||||
Schema schema14 = openAPI.getComponents().getSchemas().get("OneOfAnyType");
|
||||
assertEquals(schema14.getOneOf(), null);
|
||||
assertEquals(schema14.getType(), null);
|
||||
|
||||
Schema schema16 = openAPI.getComponents().getSchemas().get("TypeIntegerWithOneOf");
|
||||
// oneOf should have been removed as the schema is essentially a primitive type
|
||||
assertEquals(schema16.getOneOf(), null);
|
||||
|
||||
Schema schema18 = openAPI.getComponents().getSchemas().get("OneOfNullAndRef3");
|
||||
// original oneOf removed and simplified to just $ref (oneOf sub-schema) instead
|
||||
assertEquals(schema18.getOneOf(), null);
|
||||
assertEquals(schema18.get$ref(), "#/components/schemas/Parent");
|
||||
}
|
||||
}
|
||||
|
@ -112,3 +112,29 @@ components:
|
||||
- type: integer
|
||||
- type: array
|
||||
items: {}
|
||||
TypeIntegerWithOneOf:
|
||||
type: integer
|
||||
oneOf:
|
||||
- title: ITEM A
|
||||
description: This permission is for item A.
|
||||
const: 1
|
||||
- title: ITEM B
|
||||
description: This permission is for item B.
|
||||
const: 2
|
||||
- title: ITEM C
|
||||
description: This permission is for item C.
|
||||
const: 4
|
||||
format: int32
|
||||
# need to repeat the issue when it only occurs with the 3rd, 4th, 5th, etc schemas with oneOf(type: null, $ref)
|
||||
OneOfNullAndRef:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Parent'
|
||||
- type: "null"
|
||||
OneOfNullAndRef2:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Parent'
|
||||
- type: "null"
|
||||
OneOfNullAndRef3:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Parent'
|
||||
- type: "null"
|
Loading…
x
Reference in New Issue
Block a user