diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroSchemaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroSchemaCodegen.java index 5ecf732ca5b5..2fe4d50812b4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroSchemaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroSchemaCodegen.java @@ -16,6 +16,7 @@ package org.openapitools.codegen.languages; +import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.models.media.Schema; import lombok.Getter; import lombok.Setter; @@ -170,6 +171,17 @@ public String toDefaultValue(Schema p) { return null; } + // The Swagger Parser represents an explicit `default: null` (common with + // `nullable: true`, e.g. via allOf composition) as a Jackson NullNode rather than a + // Java null. Treating it as a concrete default produces an invalid Avro union such as + // `["Foo", "null"]` with `"default": null`, because Avro requires a union's default + // value to match its FIRST branch. Treat an explicit null default as "no default" so + // the field falls through to the nullable-union form `["null", "Foo"]` with + // `"default": null`, which is valid. + if (p.getDefault() instanceof JsonNode && ((JsonNode) p.getDefault()).isNull()) { + return null; + } + if (ModelUtils.isDateSchema(p) || ModelUtils.isDateTimeSchema(p) || ModelUtils.isStringSchema(p)) { return "\"" + p.getDefault().toString() + "\""; } diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6268.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6268.yaml index ce909ec3084f..8951cc936ce5 100644 --- a/modules/openapi-generator/src/test/resources/3_0/issue6268.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/issue6268.yaml @@ -19,12 +19,26 @@ paths: description: successful operation components: schemas: + AvroDefaultNullReference: + type: object + properties: + id: + type: string SampleModelToTestAvroDefaultValues: type: object required: - tagsRequired - tagsRequiredWithDefault properties: + nullableScalarWithNullDefault: + type: string + nullable: true + default: null + nullableModelWithNullDefault: + nullable: true + default: null + allOf: + - $ref: '#/components/schemas/AvroDefaultNullReference' name: type: string default: 'defaultName' diff --git a/samples/openapi3/schema/petstore/avro-schema-issue6268/.openapi-generator/FILES b/samples/openapi3/schema/petstore/avro-schema-issue6268/.openapi-generator/FILES index fb590f3217a3..efe28ee32d26 100644 --- a/samples/openapi3/schema/petstore/avro-schema-issue6268/.openapi-generator/FILES +++ b/samples/openapi3/schema/petstore/avro-schema-issue6268/.openapi-generator/FILES @@ -1 +1,2 @@ +AvroDefaultNullReference.avsc SampleModelToTestAvroDefaultValues.avsc diff --git a/samples/openapi3/schema/petstore/avro-schema-issue6268/AvroDefaultNullReference.avsc b/samples/openapi3/schema/petstore/avro-schema-issue6268/AvroDefaultNullReference.avsc new file mode 100644 index 000000000000..fccbac6e1854 --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema-issue6268/AvroDefaultNullReference.avsc @@ -0,0 +1,15 @@ +{ + "namespace": "model", + "type": "record", + "doc": "", + "name": "AvroDefaultNullReference", + "fields": [ + { + "name": "id", + "type": ["null", "string"], + "doc": "", + "default": null + } + ] + +} diff --git a/samples/openapi3/schema/petstore/avro-schema-issue6268/SampleModelToTestAvroDefaultValues.avsc b/samples/openapi3/schema/petstore/avro-schema-issue6268/SampleModelToTestAvroDefaultValues.avsc index 1ff0ad5289e0..6a5ecf7e4f23 100644 --- a/samples/openapi3/schema/petstore/avro-schema-issue6268/SampleModelToTestAvroDefaultValues.avsc +++ b/samples/openapi3/schema/petstore/avro-schema-issue6268/SampleModelToTestAvroDefaultValues.avsc @@ -4,6 +4,18 @@ "doc": "", "name": "SampleModelToTestAvroDefaultValues", "fields": [ + { + "name": "nullableScalarWithNullDefault", + "type": ["null", "string"], + "doc": "", + "default": null + }, + { + "name": "nullableModelWithNullDefault", + "type": ["null", "model.AvroDefaultNullReference"], + "doc": "", + "default": null + }, { "name": "name", "type": ["string", "null"],