forked from loafle/openapi-generator-original
Add rule to simplify oneOf/anyOf (#14777)
* add rule to simplify oneof/anyof * update doc * test nullable
This commit is contained in:
parent
c9958e12b8
commit
e09196261a
@ -484,3 +484,10 @@ Example:
|
|||||||
```
|
```
|
||||||
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/simplifyBooleanEnum_test.yaml -o /tmp/java-okhttp/ --openapi-normalizer SIMPLIFY_BOOLEAN_ENUM=true
|
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/simplifyBooleanEnum_test.yaml -o /tmp/java-okhttp/ --openapi-normalizer SIMPLIFY_BOOLEAN_ENUM=true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `SIMPLIFY_ONEOF_ANYOF`: when set to `true`, simplify oneOf/anyOf by 1) removing null (sub-schema) and setting nullable to true instead, and 2) simplifying oneOf/anyOf with a single sub-schema to just the sub-schema itself.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/simplifyOneOfAnyOf_test.yaml -o /tmp/java-okhttp/ --openapi-normalizer SIMPLIFY_ONEOF_ANYOF=true
|
||||||
|
```
|
||||||
|
@ -63,6 +63,11 @@ public class OpenAPINormalizer {
|
|||||||
final String SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING = "SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING";
|
final String SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING = "SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING";
|
||||||
boolean simplifyAnyOfStringAndEnumString;
|
boolean simplifyAnyOfStringAndEnumString;
|
||||||
|
|
||||||
|
// when set to true, oneOf/anyOf schema with only one sub-schema is simplified to just the sub-schema
|
||||||
|
// and if sub-schema contains "null", remove it and set nullable to true instead
|
||||||
|
final String SIMPLIFY_ONEOF_ANYOF = "SIMPLIFY_ONEOF_ANYOF";
|
||||||
|
boolean simplifyOneOfAnyOf;
|
||||||
|
|
||||||
// when set to true, boolean enum will be converted to just boolean
|
// when set to true, boolean enum will be converted to just boolean
|
||||||
final String SIMPLIFY_BOOLEAN_ENUM = "SIMPLIFY_BOOLEAN_ENUM";
|
final String SIMPLIFY_BOOLEAN_ENUM = "SIMPLIFY_BOOLEAN_ENUM";
|
||||||
boolean simplifyBooleanEnum;
|
boolean simplifyBooleanEnum;
|
||||||
@ -111,6 +116,10 @@ public class OpenAPINormalizer {
|
|||||||
simplifyAnyOfStringAndEnumString = true;
|
simplifyAnyOfStringAndEnumString = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enableAll || "true".equalsIgnoreCase(rules.get(SIMPLIFY_ONEOF_ANYOF))) {
|
||||||
|
simplifyOneOfAnyOf = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (enableAll || "true".equalsIgnoreCase(rules.get(SIMPLIFY_BOOLEAN_ENUM))) {
|
if (enableAll || "true".equalsIgnoreCase(rules.get(SIMPLIFY_BOOLEAN_ENUM))) {
|
||||||
simplifyBooleanEnum = true;
|
simplifyBooleanEnum = true;
|
||||||
}
|
}
|
||||||
@ -390,27 +399,36 @@ public class OpenAPINormalizer {
|
|||||||
|
|
||||||
private Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
|
private Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
|
||||||
for (Object item : schema.getOneOf()) {
|
for (Object item : schema.getOneOf()) {
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!(item instanceof Schema)) {
|
if (!(item instanceof Schema)) {
|
||||||
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
|
throw new RuntimeException("Error! oneOf schema is not of the type Schema: " + item);
|
||||||
}
|
}
|
||||||
// normalize oenOf sub schemas one by one
|
// normalize oenOf sub schemas one by one
|
||||||
normalizeSchema((Schema) item, visitedSchemas);
|
normalizeSchema((Schema) item, visitedSchemas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process rules here
|
// process rules here
|
||||||
|
schema = processSimplifyOneOf(schema);
|
||||||
|
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
|
private Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
|
||||||
for (Object item : schema.getAnyOf()) {
|
for (Object item : schema.getAnyOf()) {
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(item instanceof Schema)) {
|
if (!(item instanceof Schema)) {
|
||||||
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
|
throw new RuntimeException("Error! anyOf schema is not of the type Schema: " + item);
|
||||||
}
|
}
|
||||||
// normalize anyOf sub schemas one by one
|
// normalize anyOf sub schemas one by one
|
||||||
normalizeSchema((Schema) item, visitedSchemas);
|
normalizeSchema((Schema) item, visitedSchemas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process rules here
|
// process rules here
|
||||||
|
schema = processSimplifyAnyOf(schema);
|
||||||
|
|
||||||
// last rule to process as the schema may become String schema (not "anyOf") after the completion
|
// last rule to process as the schema may become String schema (not "anyOf") after the completion
|
||||||
return processSimplifyAnyOfStringAndEnumString(schema);
|
return processSimplifyAnyOfStringAndEnumString(schema);
|
||||||
@ -506,7 +524,7 @@ public class OpenAPINormalizer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If the schema is anyOf and the sub-schemas are either string or enum of string,
|
* If the schema is anyOf and the sub-schemas are either string or enum of string,
|
||||||
* then simply it to just string as many generators do not yet support anyOf.
|
* then simplify it to just string as many generators do not yet support anyOf.
|
||||||
*
|
*
|
||||||
* @param schema Schema
|
* @param schema Schema
|
||||||
* @return Schema
|
* @return Schema
|
||||||
@ -541,6 +559,72 @@ public class OpenAPINormalizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the schema is oneOf and the sub-schemas is null, set `nullable: true` instead.
|
||||||
|
* If there's only one sub-schema, simply return the sub-schema directly.
|
||||||
|
*
|
||||||
|
* @param schema Schema
|
||||||
|
* @return Schema
|
||||||
|
*/
|
||||||
|
private Schema processSimplifyOneOf(Schema schema) {
|
||||||
|
if (!simplifyOneOfAnyOf && !enableAll) {
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema.getOneOf() != null && !schema.getOneOf().isEmpty()) {
|
||||||
|
// convert null sub-schema to `nullable: true`
|
||||||
|
for (int i = 0; i < schema.getOneOf().size(); i++) {
|
||||||
|
if (schema.getOneOf().get(i) == null || ((Schema) schema.getOneOf().get(i)).getType() == null) {
|
||||||
|
schema.getOneOf().remove(i);
|
||||||
|
schema.setNullable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if only one element left, simplify to just the element (schema)
|
||||||
|
if (schema.getOneOf().size() == 1) {
|
||||||
|
if (schema.getNullable()) { // retain nullable setting
|
||||||
|
((Schema) schema.getOneOf().get(0)).setNullable(true);
|
||||||
|
}
|
||||||
|
return (Schema) schema.getOneOf().get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the schema is anyOf and the sub-schemas is null, set `nullable: true` instead.
|
||||||
|
* If there's only one sub-schema, simply return the sub-schema directly.
|
||||||
|
*
|
||||||
|
* @param schema Schema
|
||||||
|
* @return Schema
|
||||||
|
*/
|
||||||
|
private Schema processSimplifyAnyOf(Schema schema) {
|
||||||
|
if (!simplifyOneOfAnyOf && !enableAll) {
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema.getAnyOf() != null && !schema.getAnyOf().isEmpty()) {
|
||||||
|
// convert null sub-schema to `nullable: true`
|
||||||
|
for (int i = 0; i < schema.getAnyOf().size(); i++) {
|
||||||
|
if (schema.getAnyOf().get(i) == null || ((Schema) schema.getAnyOf().get(i)).getType() == null) {
|
||||||
|
schema.getAnyOf().remove(i);
|
||||||
|
schema.setNullable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if only one element left, simplify to just the element (schema)
|
||||||
|
if (schema.getAnyOf().size() == 1) {
|
||||||
|
if (schema.getNullable()) { // retain nullable setting
|
||||||
|
((Schema) schema.getAnyOf().get(0)).setNullable(true);
|
||||||
|
}
|
||||||
|
return (Schema) schema.getAnyOf().get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the schema is boolean and its enum is defined,
|
* If the schema is boolean and its enum is defined,
|
||||||
* then simply it to just boolean.
|
* then simply it to just boolean.
|
||||||
|
@ -4395,6 +4395,42 @@ public class DefaultCodegenTest {
|
|||||||
assertTrue(schema3 instanceof StringSchema);
|
assertTrue(schema3 instanceof StringSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOpenAPINormalizerSimplifyOneOfAnyOf() {
|
||||||
|
// to test the rule SIMPLIFY_ONEOF_ANYOF
|
||||||
|
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyOneOfAnyOf_test.yaml");
|
||||||
|
|
||||||
|
Schema schema = openAPI.getComponents().getSchemas().get("AnyOfTest");
|
||||||
|
assertEquals(schema.getAnyOf().size(), 2);
|
||||||
|
assertNull(schema.getNullable());
|
||||||
|
|
||||||
|
Schema schema2 = openAPI.getComponents().getSchemas().get("OneOfTest");
|
||||||
|
assertEquals(schema2.getOneOf().size(), 2);
|
||||||
|
assertNull(schema2.getNullable());
|
||||||
|
|
||||||
|
Schema schema5 = openAPI.getComponents().getSchemas().get("OneOfNullableTest");
|
||||||
|
assertEquals(schema5.getOneOf().size(), 3);
|
||||||
|
assertNull(schema5.getNullable());
|
||||||
|
|
||||||
|
Map<String, String> options = new HashMap<>();
|
||||||
|
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
|
||||||
|
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||||
|
openAPINormalizer.normalize();
|
||||||
|
|
||||||
|
Schema schema3 = openAPI.getComponents().getSchemas().get("AnyOfTest");
|
||||||
|
assertNull(schema3.getAnyOf());
|
||||||
|
assertTrue(schema3 instanceof StringSchema);
|
||||||
|
assertTrue(schema3.getNullable());
|
||||||
|
|
||||||
|
Schema schema4 = openAPI.getComponents().getSchemas().get("OneOfTest");
|
||||||
|
assertNull(schema4.getOneOf());
|
||||||
|
assertTrue(schema4 instanceof IntegerSchema);
|
||||||
|
|
||||||
|
Schema schema6 = openAPI.getComponents().getSchemas().get("OneOfNullableTest");
|
||||||
|
assertEquals(schema6.getOneOf().size(), 2);
|
||||||
|
assertTrue(schema6.getNullable());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOpenAPINormalizerSimplifyBooleanEnum() {
|
public void testOpenAPINormalizerSimplifyBooleanEnum() {
|
||||||
// to test the rule SIMPLIFY_BOOLEAN_ENUM
|
// to test the rule SIMPLIFY_BOOLEAN_ENUM
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
openapi: 3.0.1
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: Example
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: http://api.example.xyz/v1
|
||||||
|
paths:
|
||||||
|
/person/display/{personId}:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- name: personId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The id of the person to retrieve
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
operationId: list
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/AnyOfTest"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
AnyOfTest:
|
||||||
|
description: to test anyOf
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: null
|
||||||
|
OneOfTest:
|
||||||
|
description: to test oneOf
|
||||||
|
oneOf:
|
||||||
|
- type: integer
|
||||||
|
- $ref: null
|
||||||
|
OneOfNullableTest:
|
||||||
|
description: to test oneOf nullable
|
||||||
|
oneOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
- $ref: null
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user