avro-kotlin / avro4k

Avro format support for Kotlin
Apache License 2.0
194 stars 37 forks source link

Calling Schema::overrideNamespace disables default values for enums #121

Closed cgadski closed 2 years ago

cgadski commented 2 years ago

Problem Description

When I override the namespace of a Schema and write it to a string, default values for enum types disappear.

Minimal Working Example

import com.github.avrokotlin.avro4k.Avro
import com.github.avrokotlin.avro4k.AvroEnumDefault
import com.github.avrokotlin.avro4k.AvroNamespace
import com.github.avrokotlin.avro4k.schema.overrideNamespace
import kotlinx.serialization.Serializable
import java.io.File

@Serializable
@AvroEnumDefault("UNKNOWN")
@AvroNamespace("com.example")
enum class EnumWithDefault {
    UNKNOWN, A, B
}

@Serializable
data class Wrap(val a: EnumWithDefault)

fun main() {
    for (useNamespace in listOf(false, true)) {
        var schema = Avro.default.schema(Wrap.serializer())
        var name = "schema"
        if (useNamespace) {
            schema = schema.overrideNamespace("com.example.another_namespace")
            name += "_with_namespace"
        }
        File("$name.json").absoluteFile.let {
            println("Writing '${it.path}'...")
            it.writeText(schema.toString(true))
        }
    }
}

This writes the following two files:

--- schema.json
{
  "type" : "record",
  "name" : "Wrap",
  "namespace" : "cg.problem",
  "fields" : [ {
    "name" : "a",
    "type" : {
      "type" : "enum",
      "name" : "EnumWithDefault",
      "namespace" : "com.example",
      "symbols" : [ "UNKNOWN", "A", "B" ],
      "default" : "UNKNOWN"
    }
  } ]
}
--- schema_with_namespace.json
{
  "type" : "record",
  "name" : "Wrap",
  "namespace" : "com.example.another_namespace",
  "fields" : [ {
    "name" : "a",
    "type" : {
      "type" : "enum",
      "name" : "EnumWithDefault",
      "symbols" : [ "UNKNOWN", "A", "B" ]
    }
  } ]
}

Of course, I would like schema_with_namespace.json to also define a default value for EnumWithDefault.

Workarounds

Instead of using overrideNamespace, consider annotating your top-level class with @AvroNamespace.

Versions

I defined the following plugin / library versions in my gradle buildscript.

plugins {
    kotlin("jvm") version "1.6.0"
    kotlin("plugin.serialization") version "1.5.31"
    application
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.github.avro-kotlin.avro4k:avro4k-core:1.5.0")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1")
}
thake commented 2 years ago

@cgadski once again thanks for raising this issue :). Fixed with #123.