forked from loafle/openapi-generator-original
refacot is null schema check (#19873)
This commit is contained in:
parent
2354d402a8
commit
3b3f9a770a
@ -951,68 +951,7 @@ public class OpenAPINormalizer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(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
|
|
||||||
String type = (String) schema.getTypes().iterator().next();
|
|
||||||
return type == null || "null".equals(type);
|
|
||||||
} else { // more than 1 type so must not be just null
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema instanceof JsonSchema) { // 3.1 spec
|
|
||||||
if (Boolean.TRUE.equals(schema.getNullable())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for `type: null`
|
|
||||||
if (schema.getTypes() == null && schema.get$ref() == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else { // 3.0.x or 2.x spec
|
|
||||||
if ((schema.getType() == null || schema.getType().equals("null")) && schema.get$ref() == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the schema is oneOf and the sub-schemas is null, set `nullable: true`
|
* If the schema is oneOf and the sub-schemas is null, set `nullable: true`
|
||||||
@ -1056,7 +995,7 @@ public class OpenAPINormalizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oneOfSchemas.removeIf(oneOf -> isNullTypeSchema(openAPI, oneOf))) {
|
if (oneOfSchemas.removeIf(oneOf -> ModelUtils.isNullTypeSchema(openAPI, oneOf))) {
|
||||||
schema.setNullable(true);
|
schema.setNullable(true);
|
||||||
|
|
||||||
// if only one element left, simplify to just the element (schema)
|
// if only one element left, simplify to just the element (schema)
|
||||||
@ -1192,7 +1131,7 @@ public class OpenAPINormalizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anyOfSchemas.removeIf(anyOf -> isNullTypeSchema(openAPI, anyOf))) {
|
if (anyOfSchemas.removeIf(anyOf -> ModelUtils.isNullTypeSchema(openAPI, anyOf))) {
|
||||||
schema.setNullable(true);
|
schema.setNullable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2199,6 +2199,69 @@ public class ModelUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 static 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
|
||||||
|
String type = (String) schema.getTypes().iterator().next();
|
||||||
|
return type == null || "null".equals(type);
|
||||||
|
} else { // more than 1 type so must not be just null
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema instanceof JsonSchema) { // 3.1 spec
|
||||||
|
if (Boolean.TRUE.equals(schema.getNullable())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for `type: null`
|
||||||
|
if (schema.getTypes() == null && schema.get$ref() == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else { // 3.0.x or 2.x spec
|
||||||
|
if ((schema.getType() == null || schema.getType().equals("null")) && schema.get$ref() == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
private interface OpenAPISchemaVisitor {
|
private interface OpenAPISchemaVisitor {
|
||||||
|
|
||||||
|
@ -107,15 +107,6 @@ public class OpenAPINormalizerTest {
|
|||||||
assertTrue(schema3.getEnum().size() > 0);
|
assertTrue(schema3.getEnum().size() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isNullTypeSchemaTest() {
|
|
||||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyOneOfAnyOf_test.yaml");
|
|
||||||
Map<String, String> options = new HashMap<>();
|
|
||||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
|
||||||
Schema schema = openAPI.getComponents().getSchemas().get("AnyOfStringArrayOfString");
|
|
||||||
assertFalse(openAPINormalizer.isNullTypeSchema(openAPI, schema));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOpenAPINormalizerSimplifyOneOfAnyOf() {
|
public void testOpenAPINormalizerSimplifyOneOfAnyOf() {
|
||||||
// to test the rule SIMPLIFY_ONEOF_ANYOF
|
// to test the rule SIMPLIFY_ONEOF_ANYOF
|
||||||
|
@ -22,6 +22,7 @@ import io.swagger.v3.oas.models.media.*;
|
|||||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||||
import io.swagger.v3.oas.models.parameters.RequestBody;
|
import io.swagger.v3.oas.models.parameters.RequestBody;
|
||||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||||
|
import org.openapitools.codegen.OpenAPINormalizer;
|
||||||
import org.openapitools.codegen.TestUtils;
|
import org.openapitools.codegen.TestUtils;
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
@ -29,6 +30,9 @@ import org.testng.annotations.Test;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
public class ModelUtilsTest {
|
public class ModelUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -469,4 +473,32 @@ public class ModelUtilsTest {
|
|||||||
Assert.assertNotNull(ModelUtils.getSchemaItems((Schema) arrayWithPrefixItems.getProperties().get("with_prefixitems")));
|
Assert.assertNotNull(ModelUtils.getSchemaItems((Schema) arrayWithPrefixItems.getProperties().get("with_prefixitems")));
|
||||||
Assert.assertNotNull(ModelUtils.getSchemaItems((Schema) arrayWithPrefixItems.getProperties().get("without_items")));
|
Assert.assertNotNull(ModelUtils.getSchemaItems((Schema) arrayWithPrefixItems.getProperties().get("without_items")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isNullTypeSchemaTest() {
|
||||||
|
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/null_schema_test.yaml");
|
||||||
|
Map<String, String> options = new HashMap<>();
|
||||||
|
Schema schema = openAPI.getComponents().getSchemas().get("AnyOfStringArrayOfString");
|
||||||
|
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
|
||||||
|
|
||||||
|
schema = openAPI.getComponents().getSchemas().get("IntegerRef");
|
||||||
|
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
|
||||||
|
|
||||||
|
schema = openAPI.getComponents().getSchemas().get("OneOfAnyType");
|
||||||
|
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
|
||||||
|
|
||||||
|
schema = openAPI.getComponents().getSchemas().get("AnyOfAnyType");
|
||||||
|
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
|
||||||
|
|
||||||
|
schema = openAPI.getComponents().getSchemas().get("Parent");
|
||||||
|
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
|
||||||
|
// the dummy property is a ref to integer
|
||||||
|
assertFalse(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getProperties().get("dummy")));
|
||||||
|
|
||||||
|
schema = openAPI.getComponents().getSchemas().get("AnyOfTest");
|
||||||
|
assertFalse(ModelUtils.isNullTypeSchema(openAPI, schema));
|
||||||
|
assertTrue(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getAnyOf().get(1)));
|
||||||
|
assertTrue(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getAnyOf().get(2)));
|
||||||
|
assertTrue(ModelUtils.isNullTypeSchema(openAPI, (Schema) schema.getAnyOf().get(3)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
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'
|
||||||
|
- type: null
|
||||||
|
- $ref: null
|
||||||
|
OneOfTest:
|
||||||
|
description: to test oneOf
|
||||||
|
oneOf:
|
||||||
|
- type: integer
|
||||||
|
- type: 'null'
|
||||||
|
- type: null
|
||||||
|
- $ref: null
|
||||||
|
OneOfTest2:
|
||||||
|
description: to test oneOf
|
||||||
|
oneOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
OneOfNullableTest:
|
||||||
|
description: to test oneOf nullable
|
||||||
|
oneOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
- $ref: null
|
||||||
|
Parent:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
dummy:
|
||||||
|
$ref: '#/components/schemas/IntegerRef'
|
||||||
|
number:
|
||||||
|
anyOf:
|
||||||
|
- $ref: '#/components/schemas/Number'
|
||||||
|
AnyOfStringArrayOfString:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
AnyOfAnyType:
|
||||||
|
anyOf:
|
||||||
|
- type: boolean
|
||||||
|
- type: array
|
||||||
|
items: {}
|
||||||
|
- type: object
|
||||||
|
- type: string
|
||||||
|
- type: number
|
||||||
|
- type: integer
|
||||||
|
AnyOfAnyTypeWithRef:
|
||||||
|
anyOf:
|
||||||
|
- type: boolean
|
||||||
|
- type: array
|
||||||
|
items: { }
|
||||||
|
- type: object
|
||||||
|
- type: string
|
||||||
|
- type: number
|
||||||
|
- $ref: '#/components/schemas/IntegerRef'
|
||||||
|
IntegerRef:
|
||||||
|
type: integer
|
||||||
|
OneOfAnyType:
|
||||||
|
oneOf:
|
||||||
|
- type: object
|
||||||
|
- type: boolean
|
||||||
|
- type: number
|
||||||
|
- type: string
|
||||||
|
- type: integer
|
||||||
|
- type: array
|
||||||
|
items: {}
|
Loading…
x
Reference in New Issue
Block a user