Make the OpenAPINormalizer extensible (#20995)

* Make the OpenAPINormalizer configurable
Add comment to force rebuild

* Add documentation of NORMALIZER_CLASS

* Use default normalizeSchema() method and add a new skipNormalization method

* super.normalizedSchema() can proceed
This commit is contained in:
jpfinne 2025-04-11 13:19:56 +02:00 committed by GitHub
parent b1de687c7f
commit 4fc46cb0d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 150 additions and 65 deletions

View File

@ -601,6 +601,13 @@ Example:
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml -o /tmp/java-okhttp/ --openapi-normalizer REMOVE_X_INTERNAL=true java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/enableKeepOnlyFirstTagInOperation_test.yaml -o /tmp/java-okhttp/ --openapi-normalizer REMOVE_X_INTERNAL=true
``` ```
- `NORMALIZER_CLASS`: Set to full classname of a class extending the default org.openapitools.codegen.OpenAPINormalizer. It allows customization of the default normalizer.
Example:
```
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/required-properties.yaml -o /tmp/java-okhttp/ --openapi-normalizer NORMALIZER_CLASS=org.openapitools.codegen.OpenAPINormalizerTest$RemoveRequiredNormalizer
```
- `FILTER` - `FILTER`
The `FILTER` parameter allows selective inclusion of API operations based on specific criteria. It applies the `x-internal: true` property to operations that do **not** match the specified values, preventing them from being generated. The `FILTER` parameter allows selective inclusion of API operations based on specific criteria. It applies the `x-internal: true` property to operations that do **not** match the specified values, preventing them from being generated.

View File

@ -261,7 +261,7 @@ public class DefaultGenerator implements Generator {
if (version.atLeast("3.1.0")) { if (version.atLeast("3.1.0")) {
config.openapiNormalizer().put("NORMALIZE_31SPEC", "true"); config.openapiNormalizer().put("NORMALIZE_31SPEC", "true");
} }
OpenAPINormalizer openapiNormalizer = new OpenAPINormalizer(openAPI, config.openapiNormalizer()); OpenAPINormalizer openapiNormalizer = OpenAPINormalizer.createNormalizer(openAPI, config.openapiNormalizer());
openapiNormalizer.normalize(); openapiNormalizer.normalize();
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -32,6 +32,8 @@ import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -39,13 +41,13 @@ import java.util.stream.Collectors;
import static org.openapitools.codegen.utils.StringUtils.getUniqueString; import static org.openapitools.codegen.utils.StringUtils.getUniqueString;
public class OpenAPINormalizer { public class OpenAPINormalizer {
private OpenAPI openAPI; protected OpenAPI openAPI;
private Map<String, String> inputRules = new HashMap<>(); private Map<String, String> inputRules = new HashMap<>();
private Map<String, Boolean> rules = new HashMap<>(); private Map<String, Boolean> rules = new HashMap<>();
private TreeSet<String> anyTypeTreeSet = new TreeSet<>(); private TreeSet<String> anyTypeTreeSet = new TreeSet<>();
final Logger LOGGER = LoggerFactory.getLogger(OpenAPINormalizer.class); protected final Logger LOGGER = LoggerFactory.getLogger(OpenAPINormalizer.class);
Set<String> ruleNames = new TreeSet<>(); Set<String> ruleNames = new TreeSet<>();
Set<String> rulesDefaultToTrue = new TreeSet<>(); Set<String> rulesDefaultToTrue = new TreeSet<>();
@ -59,6 +61,9 @@ public class OpenAPINormalizer {
final String DISABLE_ALL = "DISABLE_ALL"; final String DISABLE_ALL = "DISABLE_ALL";
boolean disableAll; boolean disableAll;
// when defined, use the class name to instantiate the normalizer
static final String NORMALIZER_CLASS = "NORMALIZER_CLASS";
// when set to true, $ref in allOf is treated as parent so that x-parent: true will be added // when set to true, $ref in allOf is treated as parent so that x-parent: true will be added
// to the schema in $ref (if x-parent is not present) // to the schema in $ref (if x-parent is not present)
final String REF_AS_PARENT_IN_ALLOF = "REF_AS_PARENT_IN_ALLOF"; final String REF_AS_PARENT_IN_ALLOF = "REF_AS_PARENT_IN_ALLOF";
@ -146,6 +151,25 @@ public class OpenAPINormalizer {
// ============= end of rules ============= // ============= end of rules =============
/**
* Factory constructor for OpenAPINormalizer.
*
* Default can be overriden by setting the NORMALIZER_CLASS rule
*/
public static OpenAPINormalizer createNormalizer(OpenAPI openAPI, Map<String, String> inputRules) {
if (inputRules.containsKey(NORMALIZER_CLASS)) {
try {
Class clazz = Class.forName(inputRules.get(NORMALIZER_CLASS));
Constructor constructor = clazz.getConstructor(OpenAPI.class, Map.class);
return (OpenAPINormalizer) constructor.newInstance(openAPI, inputRules);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
} else {
return new OpenAPINormalizer(openAPI, inputRules);
}
}
/** /**
* Initializes OpenAPI Normalizer with a set of rules * Initializes OpenAPI Normalizer with a set of rules
* *
@ -162,6 +186,7 @@ public class OpenAPINormalizer {
} }
// a set of ruleNames // a set of ruleNames
ruleNames.add(NORMALIZER_CLASS);
ruleNames.add(REF_AS_PARENT_IN_ALLOF); ruleNames.add(REF_AS_PARENT_IN_ALLOF);
ruleNames.add(REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIES_ONLY); ruleNames.add(REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIES_ONLY);
ruleNames.add(SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING); ruleNames.add(SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING);
@ -318,7 +343,7 @@ public class OpenAPINormalizer {
* Normalizes the OpenAPI input, which may not perfectly conform to * Normalizes the OpenAPI input, which may not perfectly conform to
* the specification. * the specification.
*/ */
void normalize() { protected void normalize() {
if (rules == null || rules.isEmpty() || disableAll) { if (rules == null || rules.isEmpty() || disableAll) {
return; return;
} }
@ -341,7 +366,7 @@ public class OpenAPINormalizer {
/** /**
* Pre-populate info if it's not defined. * Pre-populate info if it's not defined.
*/ */
private void normalizeInfo() { protected void normalizeInfo() {
if (this.openAPI.getInfo() == null) { if (this.openAPI.getInfo() == null) {
Info info = new Info(); Info info = new Info();
info.setTitle("OpenAPI"); info.setTitle("OpenAPI");
@ -354,7 +379,7 @@ public class OpenAPINormalizer {
/** /**
* Normalizes inline models in Paths * Normalizes inline models in Paths
*/ */
private void normalizePaths() { protected void normalizePaths() {
Paths paths = openAPI.getPaths(); Paths paths = openAPI.getPaths();
if (paths == null) { if (paths == null) {
return; return;
@ -429,7 +454,7 @@ public class OpenAPINormalizer {
* *
* @param operation Operation * @param operation Operation
*/ */
private void normalizeOperation(Operation operation) { protected void normalizeOperation(Operation operation) {
processRemoveXInternalFromOperation(operation); processRemoveXInternalFromOperation(operation);
processKeepOnlyFirstTagInOperation(operation); processKeepOnlyFirstTagInOperation(operation);
@ -448,7 +473,7 @@ public class OpenAPINormalizer {
* *
* @param content target content * @param content target content
*/ */
private void normalizeContent(Content content) { protected void normalizeContent(Content content) {
if (content == null || content.isEmpty()) { if (content == null || content.isEmpty()) {
return; return;
} }
@ -472,7 +497,7 @@ public class OpenAPINormalizer {
* *
* @param operation target operation * @param operation target operation
*/ */
private void normalizeRequestBody(Operation operation) { protected void normalizeRequestBody(Operation operation) {
RequestBody requestBody = operation.getRequestBody(); RequestBody requestBody = operation.getRequestBody();
if (requestBody == null) { if (requestBody == null) {
return; return;
@ -496,7 +521,7 @@ public class OpenAPINormalizer {
* *
* @param parameters List parameters * @param parameters List parameters
*/ */
private void normalizeParameters(List<Parameter> parameters) { protected void normalizeParameters(List<Parameter> parameters) {
if (parameters == null) { if (parameters == null) {
return; return;
} }
@ -519,7 +544,7 @@ public class OpenAPINormalizer {
* *
* @param operation target operation * @param operation target operation
*/ */
private void normalizeResponses(Operation operation) { protected void normalizeResponses(Operation operation) {
ApiResponses responses = operation.getResponses(); ApiResponses responses = operation.getResponses();
if (responses == null) { if (responses == null) {
return; return;
@ -535,7 +560,7 @@ public class OpenAPINormalizer {
* *
* @param apiResponse API response * @param apiResponse API response
*/ */
private void normalizeResponse(ApiResponse apiResponse) { protected void normalizeResponse(ApiResponse apiResponse) {
if (apiResponse != null) { if (apiResponse != null) {
normalizeContent(ModelUtils.getReferencedApiResponse(openAPI, apiResponse).getContent()); normalizeContent(ModelUtils.getReferencedApiResponse(openAPI, apiResponse).getContent());
normalizeHeaders(ModelUtils.getReferencedApiResponse(openAPI, apiResponse).getHeaders()); normalizeHeaders(ModelUtils.getReferencedApiResponse(openAPI, apiResponse).getHeaders());
@ -547,7 +572,7 @@ public class OpenAPINormalizer {
* *
* @param headers a map of headers * @param headers a map of headers
*/ */
private void normalizeHeaders(Map<String, Header> headers) { protected void normalizeHeaders(Map<String, Header> headers) {
if (headers == null || headers.isEmpty()) { if (headers == null || headers.isEmpty()) {
return; return;
} }
@ -562,7 +587,7 @@ public class OpenAPINormalizer {
/** /**
* Normalizes securitySchemes in components * Normalizes securitySchemes in components
*/ */
private void normalizeComponentsSecuritySchemes() { protected void normalizeComponentsSecuritySchemes() {
if (StringUtils.isEmpty(bearerAuthSecuritySchemeName)) { if (StringUtils.isEmpty(bearerAuthSecuritySchemeName)) {
return; return;
} }
@ -592,7 +617,7 @@ public class OpenAPINormalizer {
/** /**
* Normalizes schemas in components * Normalizes schemas in components
*/ */
private void normalizeComponentsSchemas() { protected void normalizeComponentsSchemas() {
Map<String, Schema> schemas = openAPI.getComponents().getSchemas(); Map<String, Schema> schemas = openAPI.getComponents().getSchemas();
if (schemas == null) { if (schemas == null) {
return; return;
@ -623,7 +648,7 @@ public class OpenAPINormalizer {
/** /**
* Normalizes schemas in component's responses. * Normalizes schemas in component's responses.
*/ */
private void normalizeComponentsResponses() { protected void normalizeComponentsResponses() {
Map<String, ApiResponse> apiResponses = openAPI.getComponents().getResponses(); Map<String, ApiResponse> apiResponses = openAPI.getComponents().getResponses();
if (apiResponses == null) { if (apiResponses == null) {
return; return;
@ -675,7 +700,7 @@ public class OpenAPINormalizer {
} }
private boolean isSelfReference(String name, Schema subSchema) { protected boolean isSelfReference(String name, Schema subSchema) {
if (subSchema != null && name.equals(ModelUtils.getSimpleRef(subSchema.get$ref()))) { if (subSchema != null && name.equals(ModelUtils.getSimpleRef(subSchema.get$ref()))) {
return true; return true;
} else { } else {
@ -691,20 +716,10 @@ public class OpenAPINormalizer {
* @return Schema * @return Schema
*/ */
public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) { public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
if (schema == null) { if (skipNormalization(schema, visitedSchemas)) {
return schema; return schema;
} }
markSchemaAsVisited(schema, visitedSchemas);
if (StringUtils.isNotEmpty(schema.get$ref())) {
// no need to process $ref
return schema;
}
if (visitedSchemas.contains(schema)) {
return schema; // skip due to circular reference
} else {
visitedSchemas.add(schema);
}
if (ModelUtils.isArraySchema(schema)) { // array if (ModelUtils.isArraySchema(schema)) { // array
Schema result = normalizeArraySchema(schema); Schema result = normalizeArraySchema(schema);
@ -758,35 +773,73 @@ public class OpenAPINormalizer {
} else { } else {
throw new RuntimeException("Unknown schema type found in normalizer: " + schema); throw new RuntimeException("Unknown schema type found in normalizer: " + schema);
} }
return schema; return schema;
} }
private Schema normalizeArraySchema(Schema schema) {
/**
* Check if normalization is needed.
*
* No normalization needed if the schema is null or is a $ref or already processed.
*
* @param schema Schema
* @param visitedSchemas a set of visited schemas
* @return false if normalization is needed
*/
protected boolean skipNormalization(Schema schema, Set<Schema> visitedSchemas) {
if (schema == null) {
return true;
}
if (StringUtils.isNotEmpty(schema.get$ref())) {
// no need to process $ref
return true;
}
if (visitedSchemas.contains(schema)) {
return true; // skip due to circular reference
} else {
return false;
}
}
/**
* Add the schema to the collection of visited schemas.
*
* @param schema schema to add
* @param visitedSchemas current visited schemas
*/
protected void markSchemaAsVisited(Schema schema, Set<Schema> visitedSchemas) {
if (schema != null) {
visitedSchemas.add(schema);
}
}
protected Schema normalizeArraySchema(Schema schema) {
Schema result = processNormalize31Spec(schema, new HashSet<>()); Schema result = processNormalize31Spec(schema, new HashSet<>());
return processSetArraytoNullable(result); return processSetArraytoNullable(result);
} }
private Schema normalizeMapSchema(Schema schema) { protected Schema normalizeMapSchema(Schema schema) {
return processSetMapToNullable(schema); return processSetMapToNullable(schema);
} }
private Schema normalizeSimpleSchema(Schema schema, Set<Schema> visitedSchemas) { protected Schema normalizeSimpleSchema(Schema schema, Set<Schema> visitedSchemas) {
Schema result = processNormalize31Spec(schema, visitedSchemas); Schema result = processNormalize31Spec(schema, visitedSchemas);
return processSetPrimitiveTypesToNullable(result); return processSetPrimitiveTypesToNullable(result);
} }
private void normalizeBooleanSchema(Schema schema, Set<Schema> visitedSchemas) { protected void normalizeBooleanSchema(Schema schema, Set<Schema> visitedSchemas) {
processSimplifyBooleanEnum(schema); processSimplifyBooleanEnum(schema);
processSetPrimitiveTypesToNullable(schema); processSetPrimitiveTypesToNullable(schema);
} }
private void normalizeIntegerSchema(Schema schema, Set<Schema> visitedSchemas) { protected void normalizeIntegerSchema(Schema schema, Set<Schema> visitedSchemas) {
processAddUnsignedToIntegerWithInvalidMaxValue(schema); processAddUnsignedToIntegerWithInvalidMaxValue(schema);
processSetPrimitiveTypesToNullable(schema); processSetPrimitiveTypesToNullable(schema);
} }
private void normalizeProperties(Map<String, Schema> properties, Set<Schema> visitedSchemas) { protected void normalizeProperties(Map<String, Schema> properties, Set<Schema> visitedSchemas) {
if (properties == null) { if (properties == null) {
return; return;
} }
@ -802,7 +855,7 @@ public class OpenAPINormalizer {
* *
* @param schema Schema * @param schema Schema
*/ */
private void removeUnsupportedSchemasFromAllOf(Schema schema) { protected void removeUnsupportedSchemasFromAllOf(Schema schema) {
if (schema.getAllOf() == null) { if (schema.getAllOf() == null) {
return; return;
} }
@ -825,7 +878,7 @@ public class OpenAPINormalizer {
} }
} }
private Schema normalizeAllOf(Schema schema, Set<Schema> visitedSchemas) { protected Schema normalizeAllOf(Schema schema, Set<Schema> visitedSchemas) {
removeUnsupportedSchemasFromAllOf(schema); removeUnsupportedSchemasFromAllOf(schema);
if (schema.getAllOf() == null) { if (schema.getAllOf() == null) {
@ -846,7 +899,7 @@ public class OpenAPINormalizer {
return schema; return schema;
} }
private Schema normalizeAllOfWithProperties(Schema schema, Set<Schema> visitedSchemas) { protected Schema normalizeAllOfWithProperties(Schema schema, Set<Schema> visitedSchemas) {
removeUnsupportedSchemasFromAllOf(schema); removeUnsupportedSchemasFromAllOf(schema);
if (schema.getAllOf() == null) { if (schema.getAllOf() == null) {
@ -867,7 +920,7 @@ public class OpenAPINormalizer {
return schema; return schema;
} }
private Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) { protected Schema normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
// simplify first as the schema may no longer be a oneOf after processing the rule below // simplify first as the schema may no longer be a oneOf after processing the rule below
schema = processSimplifyOneOf(schema); schema = processSimplifyOneOf(schema);
@ -895,7 +948,7 @@ public class OpenAPINormalizer {
return schema; return schema;
} }
private Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) { protected Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
for (int i = 0; i < schema.getAnyOf().size(); i++) { for (int i = 0; i < schema.getAnyOf().size(); i++) {
// normalize anyOf sub schemas one by one // normalize anyOf sub schemas one by one
Object item = schema.getAnyOf().get(i); Object item = schema.getAnyOf().get(i);
@ -919,7 +972,7 @@ public class OpenAPINormalizer {
return normalizeSchema(processSimplifyAnyOfStringAndEnumString(schema), visitedSchemas); return normalizeSchema(processSimplifyAnyOfStringAndEnumString(schema), visitedSchemas);
} }
private Schema normalizeComplexComposedSchema(Schema schema, Set<Schema> visitedSchemas) { protected Schema normalizeComplexComposedSchema(Schema schema, Set<Schema> visitedSchemas) {
// loop through properties, if any // loop through properties, if any
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
normalizeProperties(schema.getProperties(), visitedSchemas); normalizeProperties(schema.getProperties(), visitedSchemas);
@ -938,7 +991,7 @@ public class OpenAPINormalizer {
* *
* @param schema Schema * @param schema Schema
*/ */
private void processUseAllOfRefAsParent(Schema schema) { protected void processUseAllOfRefAsParent(Schema schema) {
if (!getRule(REF_AS_PARENT_IN_ALLOF)) { if (!getRule(REF_AS_PARENT_IN_ALLOF)) {
return; return;
} }
@ -984,7 +1037,7 @@ public class OpenAPINormalizer {
* *
* @param operation Operation * @param operation Operation
*/ */
private void processRemoveXInternalFromOperation(Operation operation) { protected void processRemoveXInternalFromOperation(Operation operation) {
if (!getRule(REMOVE_X_INTERNAL)) { if (!getRule(REMOVE_X_INTERNAL)) {
return; return;
} }
@ -1004,7 +1057,7 @@ public class OpenAPINormalizer {
* *
* @param operation Operation * @param operation Operation
*/ */
private void processKeepOnlyFirstTagInOperation(Operation operation) { protected void processKeepOnlyFirstTagInOperation(Operation operation) {
if (!getRule(KEEP_ONLY_FIRST_TAG_IN_OPERATION)) { if (!getRule(KEEP_ONLY_FIRST_TAG_IN_OPERATION)) {
return; return;
} }
@ -1022,7 +1075,7 @@ public class OpenAPINormalizer {
* *
* @param operation Operation * @param operation Operation
*/ */
private void processSetTagsForAllOperations(Operation operation) { protected void processSetTagsForAllOperations(Operation operation) {
if (StringUtils.isEmpty(setTagsForAllOperations)) { if (StringUtils.isEmpty(setTagsForAllOperations)) {
return; return;
} }
@ -1036,7 +1089,7 @@ public class OpenAPINormalizer {
* *
* @param operation Operation * @param operation Operation
*/ */
private void processSetTagsToOperationId(Operation operation) { protected void processSetTagsToOperationId(Operation operation) {
if (!getRule(SET_TAGS_TO_OPERATIONID)) { if (!getRule(SET_TAGS_TO_OPERATIONID)) {
return; return;
} }
@ -1054,7 +1107,7 @@ public class OpenAPINormalizer {
* *
* @param operation Operation * @param operation Operation
*/ */
private void processSetTagsToVendorExtension(Operation operation) { protected void processSetTagsToVendorExtension(Operation operation) {
if (StringUtils.isEmpty(setTagsToVendorExtension)) { if (StringUtils.isEmpty(setTagsToVendorExtension)) {
return; return;
} }
@ -1077,7 +1130,7 @@ public class OpenAPINormalizer {
} }
} }
private void processFixDuplicatedOperationId(Operation operation) { protected void processFixDuplicatedOperationId(Operation operation) {
if (!getRule(FIX_DUPLICATED_OPERATIONID)) { if (!getRule(FIX_DUPLICATED_OPERATIONID)) {
return; return;
} }
@ -1101,7 +1154,7 @@ public class OpenAPINormalizer {
* *
* @param schema Schema * @param schema Schema
*/ */
private void processRemoveAnyOfOneOfAndKeepPropertiesOnly(Schema schema) { protected void processRemoveAnyOfOneOfAndKeepPropertiesOnly(Schema schema) {
if (!getRule(REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIES_ONLY)) { if (!getRule(REMOVE_ANYOF_ONEOF_AND_KEEP_PROPERTIES_ONLY)) {
return; return;
} }
@ -1123,7 +1176,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private Schema processSimplifyAnyOfStringAndEnumString(Schema schema) { protected Schema processSimplifyAnyOfStringAndEnumString(Schema schema) {
if (!getRule(SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING)) { if (!getRule(SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING)) {
return schema; return schema;
} }
@ -1179,7 +1232,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private Schema processSimplifyOneOf(Schema schema) { protected Schema processSimplifyOneOf(Schema schema) {
if (!getRule(SIMPLIFY_ONEOF_ANYOF)) { if (!getRule(SIMPLIFY_ONEOF_ANYOF)) {
return schema; return schema;
} }
@ -1240,7 +1293,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private Schema processSetArraytoNullable(Schema schema) { protected Schema processSetArraytoNullable(Schema schema) {
if (!getRule(SET_CONTAINER_TO_NULLABLE)) { if (!getRule(SET_CONTAINER_TO_NULLABLE)) {
return schema; return schema;
} }
@ -1264,7 +1317,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private Schema processSetPrimitiveTypesToNullable(Schema schema) { protected Schema processSetPrimitiveTypesToNullable(Schema schema) {
if (!getRule(SET_PRIMITIVE_TYPES_TO_NULLABLE)) { if (!getRule(SET_PRIMITIVE_TYPES_TO_NULLABLE)) {
return schema; return schema;
} }
@ -1282,7 +1335,7 @@ public class OpenAPINormalizer {
return schema; return schema;
} }
private Schema setNullable(Schema schema) { protected Schema setNullable(Schema schema) {
if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey("x-nullable"))) { if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey("x-nullable"))) {
// already set, don't overwrite // already set, don't overwrite
return schema; return schema;
@ -1297,7 +1350,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private Schema processSetMapToNullable(Schema schema) { protected Schema processSetMapToNullable(Schema schema) {
if (!getRule(SET_CONTAINER_TO_NULLABLE)) { if (!getRule(SET_CONTAINER_TO_NULLABLE)) {
return schema; return schema;
} }
@ -1316,7 +1369,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private Schema processSimplifyAnyOf(Schema schema) { protected Schema processSimplifyAnyOf(Schema schema) {
if (!getRule(SIMPLIFY_ONEOF_ANYOF)) { if (!getRule(SIMPLIFY_ONEOF_ANYOF)) {
return schema; return schema;
} }
@ -1373,7 +1426,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private void processSimplifyBooleanEnum(Schema schema) { protected void processSimplifyBooleanEnum(Schema schema) {
if (!getRule(SIMPLIFY_BOOLEAN_ENUM)) { if (!getRule(SIMPLIFY_BOOLEAN_ENUM)) {
return; return;
} }
@ -1393,7 +1446,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private void processAddUnsignedToIntegerWithInvalidMaxValue(Schema schema) { protected void processAddUnsignedToIntegerWithInvalidMaxValue(Schema schema) {
if (!getRule(ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE)) { if (!getRule(ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE)) {
return; return;
} }
@ -1420,7 +1473,7 @@ public class OpenAPINormalizer {
* @param schema Schema * @param schema Schema
* @return Schema * @return Schema
*/ */
private Schema processRefactorAllOfWithPropertiesOnly(Schema schema) { protected Schema processRefactorAllOfWithPropertiesOnly(Schema schema) {
if (!getRule(REFACTOR_ALLOF_WITH_PROPERTIES_ONLY)) { if (!getRule(REFACTOR_ALLOF_WITH_PROPERTIES_ONLY)) {
return schema; return schema;
} }
@ -1460,7 +1513,7 @@ public class OpenAPINormalizer {
* @param visitedSchemas a set of visited schemas * @param visitedSchemas a set of visited schemas
* @return Schema * @return Schema
*/ */
private Schema processNormalize31Spec(Schema schema, Set<Schema> visitedSchemas) { protected Schema processNormalize31Spec(Schema schema, Set<Schema> visitedSchemas) {
if (!getRule(NORMALIZE_31SPEC)) { if (!getRule(NORMALIZE_31SPEC)) {
return schema; return schema;
} }

View File

@ -24,10 +24,7 @@ import io.swagger.v3.oas.models.security.SecurityScheme;
import org.openapitools.codegen.utils.ModelUtils; import org.openapitools.codegen.utils.ModelUtils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.Arrays; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.testng.Assert.*; import static org.testng.Assert.*;
@ -965,4 +962,32 @@ public class OpenAPINormalizerTest {
assertEquals(scheme.getName(), null); assertEquals(scheme.getName(), null);
assertEquals(scheme.getIn(), null); assertEquals(scheme.getIn(), null);
} }
@Test
public void testNormalizerClass() {
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/required-properties.yaml");
Map<String, String> inputRules = Map.of(
"NORMALIZER_CLASS", RemoveRequiredNormalizer.class.getName()
);
OpenAPINormalizer openAPINormalizer = OpenAPINormalizer.createNormalizer(openAPI, inputRules);
openAPINormalizer.normalize();
Schema requiredProperties = openAPI.getComponents().getSchemas().get("RequiredProperties");
assertEquals(requiredProperties.getRequired(), null);
}
public static class RemoveRequiredNormalizer extends OpenAPINormalizer {
public RemoveRequiredNormalizer(OpenAPI openAPI, Map<String, String> inputRules) {
super(openAPI, inputRules);
}
@Override
public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
if (skipNormalization(schema, visitedSchemas)) {
return schema;
}
schema.setRequired(null);
return super.normalizeSchema(schema, visitedSchemas);
}
}
} }