feat(avro-schema): logical type support (#19607)

* feat(avro-schema): logical type support

* style: newline at eof
This commit is contained in:
Joscha Feth 2024-09-19 02:34:51 +01:00 committed by GitHub
parent 0f561b05cb
commit 171804eef7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 49 additions and 2 deletions

View File

@ -2,3 +2,6 @@ generatorName: avro-schema
outputDir: samples/openapi3/schema/petstore/avro-schema
inputSpec: modules/openapi-generator/src/test/resources/3_0/avro-schema/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/avro-schema
additionalProperties:
useLogicalTypes: true
logicalTypeTimeQuantifier: nanos

View File

@ -23,10 +23,12 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|logicalTypeTimeQuantifier|The quantifier for time-related logical types (`timestamp` and `local-timestamp`).|<dl><dt>**nanos**</dt><dd>nanoseconds</dd><dt>**micros**</dt><dd>microseconds</dd><dt>**millis**</dt><dd>milliseconds</dd></dl>|millis|
|packageName|package for generated classes (where supported)| |null|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|useLogicalTypes|Use logical types for fields, when matching OpenAPI types. Currently supported: `date-time`, `date`.| |false|
## IMPORT MAPPING

View File

@ -27,6 +27,7 @@ import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -37,11 +38,32 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.Getter;
import lombok.Setter;
public class AvroSchemaCodegen extends DefaultCodegen implements CodegenConfig {
private final Logger LOGGER = LoggerFactory.getLogger(AvroSchemaCodegen.class);
private static final String AVRO = "avro-schema";
/**
* See https://avro.apache.org/docs/++version++/specification/#logical-types
*/
public static final String USE_LOGICAL_TYPES = "useLogicalTypes";
public static final String USE_LOGICAL_TYPES_DESC = "Use logical types for fields, when matching OpenAPI types. Currently supported: `date-time`, `date`.";
/**
* See https://avro.apache.org/docs/++version++/specification/#timestamps
*/
public static final String LOGICAL_TYPES_TIME_QUANTIFIER = "logicalTypeTimeQuantifier";
public static final String LOGICAL_TYPES_TIME_QUANTIFIER_DESC = "The quantifier for time-related logical types (`timestamp` and `local-timestamp`).";
protected String packageName = "model";
@Getter @Setter
protected boolean useLogicalTypes = false; // this defaults to false for backwards compatibility
@Getter @Setter
protected String logicalTypeTimeQuantifier = "millis";
public AvroSchemaCodegen() {
super();
@ -96,6 +118,15 @@ public class AvroSchemaCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("BigDecimal", "string");
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, CodegenConstants.PACKAGE_NAME_DESC));
cliOptions.add(CliOption.newBoolean(USE_LOGICAL_TYPES, USE_LOGICAL_TYPES_DESC).defaultValue(Boolean.FALSE.toString()));
CliOption logicalTimeQuantifier = new CliOption(LOGICAL_TYPES_TIME_QUANTIFIER, LOGICAL_TYPES_TIME_QUANTIFIER_DESC).defaultValue(this.getLogicalTypeTimeQuantifier());
Map<String, String> timeQuantifierOptions = new HashMap<>();
timeQuantifierOptions.put("nanos", "nanoseconds");
timeQuantifierOptions.put("micros", "microseconds");
timeQuantifierOptions.put("millis", "milliseconds");
logicalTimeQuantifier.setEnum(timeQuantifierOptions);
cliOptions.add(logicalTimeQuantifier);
}
@Override
@ -109,6 +140,16 @@ public class AvroSchemaCodegen extends DefaultCodegen implements CodegenConfig {
}
additionalProperties.put("packageName", packageName);
if (!convertPropertyToBooleanAndWriteBack(USE_LOGICAL_TYPES, this::setUseLogicalTypes)) {
// This sets the default if the option was not specified.
additionalProperties.put(USE_LOGICAL_TYPES, useLogicalTypes);
}
if (convertPropertyToStringAndWriteBack(LOGICAL_TYPES_TIME_QUANTIFIER, this::setLogicalTypeTimeQuantifier) == null) {
// This sets the default if the option was not specified.
additionalProperties.put(LOGICAL_TYPES_TIME_QUANTIFIER, logicalTypeTimeQuantifier);
}
}
@Override

View File

@ -0,0 +1 @@
{{#useLogicalTypes}}{{#isDate}}{ "type": "int", "logicalType": "date" }{{/isDate}}{{#isDateTime}}{ "type": "long", "logicalType": "timestamp-{{{logicalTypeTimeQuantifier}}}" }{{/isDateTime}}{{^isDate}}{{^isDateTime}}"{{{dataType}}}"{{/isDateTime}}{{/isDate}}{{/useLogicalTypes}}{{^useLogicalTypes}}"{{{dataType}}}"{{/useLogicalTypes}}

View File

@ -1 +1 @@
{{^isEnum}}{{^isContainer}}{{#isPrimitiveType}}"{{dataType}}"{{/isPrimitiveType}}{{^isPrimitiveType}}"{{package}}.{{dataType}}"{{/isPrimitiveType}}{{/isContainer}}{{#isContainer}}{{>typeArray}}{{/isContainer}}{{/isEnum}}{{#isEnum}}{{>typeEnum}}{{/isEnum}}
{{^isEnum}}{{^isContainer}}{{#isPrimitiveType}}{{>dataType}}{{/isPrimitiveType}}{{^isPrimitiveType}}"{{package}}.{{dataType}}"{{/isPrimitiveType}}{{/isContainer}}{{#isContainer}}{{>typeArray}}{{/isContainer}}{{/isEnum}}{{#isEnum}}{{>typeEnum}}{{/isEnum}}

View File

@ -24,7 +24,7 @@
},
{
"name": "shipDate",
"type": ["null", "string"],
"type": ["null", { "type": "long", "logicalType": "timestamp-nanos" }],
"doc": "",
"default": null
},