mirror of
https://github.com/jlengrand/openapi-generator.git
synced 2026-03-10 08:31:23 +00:00
add rule to set primitive types to nullable (#18258)
This commit is contained in:
@@ -605,3 +605,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/petstore.yaml -o /tmp/java-okhttp/ --openapi-normalizer SET_CONTAINER_TO_NULLABLE="array|map"
|
||||
```
|
||||
|
||||
- `SET_PRIMITIVE_TYPES_TO_NULLABLE`: When set to `string|integer|number|boolean` (or just `string`) for example, it will set the type to `nullable` (nullable: true)
|
||||
|
||||
Example:
|
||||
```
|
||||
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/java-okhttp/ --openapi-normalizer SET_PRIMITIVE_TYPES_TO_NULLABLE="integer|number"
|
||||
```
|
||||
|
||||
@@ -112,6 +112,14 @@ public class OpenAPINormalizer {
|
||||
boolean updateSetToNullable;
|
||||
boolean updateMapToNullable;
|
||||
|
||||
// when set (e.g. operationId:getPetById|addPet), filter out (or remove) everything else
|
||||
final String SET_PRIMITIVE_TYPES_TO_NULLABLE = "SET_PRIMITIVE_TYPES_TO_NULLABLE";
|
||||
HashSet<String> setPrimitiveTypesToNullable = new HashSet<>();
|
||||
boolean updateStringToNullable;
|
||||
boolean updateIntegerToNullable;
|
||||
boolean updateNumberToNullable;
|
||||
boolean updateBooleanToNullable;
|
||||
|
||||
// ============= end of rules =============
|
||||
|
||||
/**
|
||||
@@ -143,6 +151,9 @@ public class OpenAPINormalizer {
|
||||
ruleNames.add(NORMALIZE_31SPEC);
|
||||
ruleNames.add(REMOVE_X_INTERNAL);
|
||||
ruleNames.add(FILTER);
|
||||
ruleNames.add(SET_CONTAINER_TO_NULLABLE);
|
||||
ruleNames.add(SET_PRIMITIVE_TYPES_TO_NULLABLE);
|
||||
|
||||
|
||||
// rules that are default to true
|
||||
rules.put(SIMPLIFY_ONEOF_ANYOF, true);
|
||||
@@ -223,6 +234,26 @@ public class OpenAPINormalizer {
|
||||
LOGGER.error("SET_CONTAINER_TO_NULLABLE rule must be in the form of `array|set|map`, e.g. `set`, `array|map`: {}", inputRules.get(SET_CONTAINER_TO_NULLABLE));
|
||||
}
|
||||
}
|
||||
|
||||
if (inputRules.get(SET_PRIMITIVE_TYPES_TO_NULLABLE) != null) {
|
||||
rules.put(SET_PRIMITIVE_TYPES_TO_NULLABLE, true);
|
||||
setPrimitiveTypesToNullable = new HashSet<>(Arrays.asList(inputRules.get(SET_PRIMITIVE_TYPES_TO_NULLABLE).split("[|]")));
|
||||
if (setPrimitiveTypesToNullable.contains("string")) {
|
||||
updateStringToNullable = true;
|
||||
}
|
||||
if (setPrimitiveTypesToNullable.contains("integer")) {
|
||||
updateIntegerToNullable = true;
|
||||
}
|
||||
if (setPrimitiveTypesToNullable.contains("number")) {
|
||||
updateNumberToNullable = true;
|
||||
}
|
||||
if (setPrimitiveTypesToNullable.contains("boolean")) {
|
||||
updateBooleanToNullable = true;
|
||||
}
|
||||
if (!updateStringToNullable && !updateIntegerToNullable && !updateNumberToNullable && !updateBooleanToNullable) {
|
||||
LOGGER.error("SET_PRIMITIVE_TYPES_TO_NULLABLE rule must be in the form of `string|integer|number|boolean`, e.g. `string`, `integer|number`: {}", inputRules.get(SET_PRIMITIVE_TYPES_TO_NULLABLE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -533,15 +564,18 @@ public class OpenAPINormalizer {
|
||||
}
|
||||
|
||||
private Schema normalizeSimpleSchema(Schema schema, Set<Schema> visitedSchemas) {
|
||||
return processNormalize31Spec(schema, visitedSchemas);
|
||||
Schema result = processNormalize31Spec(schema, visitedSchemas);
|
||||
return processSetPrimitiveTypesToNullable(result);
|
||||
}
|
||||
|
||||
private void normalizeBooleanSchema(Schema schema, Set<Schema> visitedSchemas) {
|
||||
processSimplifyBooleanEnum(schema);
|
||||
processSetPrimitiveTypesToNullable(schema);
|
||||
}
|
||||
|
||||
private void normalizeIntegerSchema(Schema schema, Set<Schema> visitedSchemas) {
|
||||
processAddUnsignedToIntegerWithInvalidMaxValue(schema);
|
||||
processSetPrimitiveTypesToNullable(schema);
|
||||
}
|
||||
|
||||
private void normalizeProperties(Map<String, Schema> properties, Set<Schema> visitedSchemas) {
|
||||
@@ -917,25 +951,49 @@ public class OpenAPINormalizer {
|
||||
|
||||
if (Boolean.TRUE.equals(schema.getUniqueItems())) { // a set
|
||||
if (updateSetToNullable) {
|
||||
if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey("x-nullable"))) {
|
||||
// already set, don't overwrite
|
||||
return schema;
|
||||
}
|
||||
schema.setNullable(true);
|
||||
return setNullable(schema);
|
||||
}
|
||||
} else { // array
|
||||
if (updateArrayToNullable) {
|
||||
if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey("x-nullable"))) {
|
||||
// already set, don't overwrite
|
||||
return schema;
|
||||
}
|
||||
schema.setNullable(true);
|
||||
return setNullable(schema);
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set nullable to true in primitive types (e.g. string) if needed.
|
||||
*
|
||||
* @param schema Schema
|
||||
* @return Schema
|
||||
*/
|
||||
private Schema processSetPrimitiveTypesToNullable(Schema schema) {
|
||||
if (!getRule(SET_PRIMITIVE_TYPES_TO_NULLABLE)) {
|
||||
return schema;
|
||||
}
|
||||
|
||||
if (updateStringToNullable && "string".equals(schema.getType())) {
|
||||
return setNullable(schema);
|
||||
} else if (updateIntegerToNullable && "integer".equals(schema.getType())) {
|
||||
return setNullable(schema);
|
||||
} else if (updateNumberToNullable && "number".equals(schema.getType())) {
|
||||
return setNullable(schema);
|
||||
} else if (updateBooleanToNullable && "boolean".equals(schema.getType())) {
|
||||
return setNullable(schema);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
private Schema setNullable(Schema schema) {
|
||||
if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey("x-nullable"))) {
|
||||
// already set, don't overwrite
|
||||
return schema;
|
||||
}
|
||||
schema.setNullable(true);
|
||||
return schema;
|
||||
}
|
||||
/**
|
||||
* Set nullable to true in map if needed.
|
||||
*
|
||||
@@ -948,11 +1006,7 @@ public class OpenAPINormalizer {
|
||||
}
|
||||
|
||||
if (updateMapToNullable) {
|
||||
if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey("x-nullable"))) {
|
||||
// already set, don't override
|
||||
return schema;
|
||||
}
|
||||
schema.setNullable(true);
|
||||
return setNullable(schema);
|
||||
}
|
||||
|
||||
return schema;
|
||||
|
||||
@@ -514,6 +514,48 @@ public class OpenAPINormalizerTest {
|
||||
assertEquals(((Schema) schema4.getProperties().get("map_property")).getNullable(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetPrimitiveTypesToNullable() {
|
||||
// test `string|integer|number|boolean`
|
||||
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0//setPrimitiveTypesToNullable_test.yaml");
|
||||
|
||||
Schema schema = openAPI.getComponents().getSchemas().get("Person");
|
||||
assertEquals(((Schema) schema.getProperties().get("lastName")).getNullable(), null);
|
||||
assertEquals(((Schema) schema.getProperties().get("first_integer")).getNullable(), null);
|
||||
assertEquals(((Schema) schema.getProperties().get("first_number")).getNullable(), null);
|
||||
assertEquals(((Schema) schema.getProperties().get("first_boolean")).getNullable(), null);
|
||||
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("SET_PRIMITIVE_TYPES_TO_NULLABLE", "string|integer|number|boolean");
|
||||
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||
openAPINormalizer.normalize();
|
||||
|
||||
Schema schema2 = openAPI.getComponents().getSchemas().get("Person");
|
||||
assertEquals(((Schema) schema2.getProperties().get("lastName")).getNullable(), true);
|
||||
assertEquals(((Schema) schema2.getProperties().get("first_integer")).getNullable(), true);
|
||||
assertEquals(((Schema) schema2.getProperties().get("first_number")).getNullable(), true);
|
||||
assertEquals(((Schema) schema2.getProperties().get("first_boolean")).getNullable(), true);
|
||||
|
||||
// test `number` only
|
||||
OpenAPI openAPI2 = TestUtils.parseSpec("src/test/resources/3_0//setPrimitiveTypesToNullable_test.yaml");
|
||||
|
||||
Schema schema3 = openAPI2.getComponents().getSchemas().get("Person");
|
||||
assertEquals(((Schema) schema3.getProperties().get("lastName")).getNullable(), null);
|
||||
assertEquals(((Schema) schema3.getProperties().get("first_integer")).getNullable(), null);
|
||||
assertEquals(((Schema) schema3.getProperties().get("first_number")).getNullable(), null);
|
||||
assertEquals(((Schema) schema3.getProperties().get("first_boolean")).getNullable(), null);
|
||||
|
||||
options.put("SET_PRIMITIVE_TYPES_TO_NULLABLE", "number");
|
||||
OpenAPINormalizer openAPINormalizer2 = new OpenAPINormalizer(openAPI2, options);
|
||||
openAPINormalizer2.normalize();
|
||||
|
||||
Schema schema4 = openAPI2.getComponents().getSchemas().get("Person");
|
||||
assertEquals(((Schema) schema4.getProperties().get("lastName")).getNullable(), null);
|
||||
assertEquals(((Schema) schema4.getProperties().get("first_integer")).getNullable(), null);
|
||||
assertEquals(((Schema) schema4.getProperties().get("first_number")).getNullable(), true);
|
||||
assertEquals(((Schema) schema4.getProperties().get("first_boolean")).getNullable(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() {
|
||||
// to test the rule SIMPLIFY_ONEOF_ANYOF in 3.1 spec
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
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:
|
||||
tags:
|
||||
- person
|
||||
- basic
|
||||
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/Person"
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Person:
|
||||
description: person
|
||||
type: object
|
||||
properties:
|
||||
lastName:
|
||||
type: string
|
||||
first_integer:
|
||||
type: integer
|
||||
first_number:
|
||||
type: number
|
||||
first_boolean:
|
||||
type: boolean
|
||||
Reference in New Issue
Block a user