diff --git a/avro4s-core/src/main/scala/com/sksamuel/avro4s/NameExtractor.scala b/avro4s-core/src/main/scala/com/sksamuel/avro4s/NameExtractor.scala index 564a56eb..dd264f65 100644 --- a/avro4s-core/src/main/scala/com/sksamuel/avro4s/NameExtractor.scala +++ b/avro4s-core/src/main/scala/com/sksamuel/avro4s/NameExtractor.scala @@ -33,7 +33,7 @@ case class NameExtractor(typeInfo: TypeInfo) { */ def fullName: String = namespace.trim() match { case "" => name - case otherwise => namespace + "." + name + case _ => namespace + "." + name } /** diff --git a/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaFor.scala b/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaFor.scala index 49fb8b5f..94be1400 100644 --- a/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaFor.scala +++ b/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaFor.scala @@ -124,7 +124,7 @@ object SchemaFor with ByteIterableSchemaFors with BaseSchemaFors { - def apply[T](schema: Schema, fieldMapper: FieldMapper = DefaultFieldMapper) = { + def apply[T](schema: Schema, fieldMapper: FieldMapper = DefaultFieldMapper): Typeclass[T] = { val s = schema val fm = fieldMapper new SchemaFor[T] { diff --git a/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaHelper.scala b/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaHelper.scala index a8728d25..cce153a5 100644 --- a/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaHelper.scala +++ b/avro4s-core/src/main/scala/com/sksamuel/avro4s/SchemaHelper.scala @@ -1,8 +1,8 @@ package com.sksamuel.avro4s -import org.apache.avro.{JsonProperties, Schema} import org.apache.avro.generic.GenericData import org.apache.avro.util.Utf8 +import org.apache.avro.{JsonProperties, Schema, SchemaBuilder} import scala.util.matching.Regex @@ -140,21 +140,27 @@ object SchemaHelper { case Schema.Type.RECORD => val fields = schema.getFields.asScala.map { field => new Schema.Field(field.name(), - overrideNamespace(field.schema(), namespace), - field.doc, - field.defaultVal, - field.order) + overrideNamespace(field.schema(), namespace), + field.doc, + field.defaultVal, + field.order) } val copy = Schema.createRecord(schema.getName, schema.getDoc, namespace, schema.isError, fields.asJava) schema.getAliases.asScala.foreach(copy.addAlias) schema.getObjectProps.asScala.foreach { case (k, v) => copy.addProp(k, v) } copy case Schema.Type.UNION => Schema.createUnion(schema.getTypes.asScala.map(overrideNamespace(_, namespace)).asJava) - case Schema.Type.ENUM => Schema.createEnum(schema.getName, schema.getDoc, namespace, schema.getEnumSymbols) + case Schema.Type.ENUM => + val symbols = schema.getEnumSymbols.asScala.toArray[String] + SchemaBuilder.enumeration(schema.getName) + .namespace(namespace) + .doc(schema.getDoc) + .defaultSymbol(schema.getEnumDefault) + .symbols(symbols: _*) case Schema.Type.FIXED => Schema.createFixed(schema.getName, schema.getDoc, namespace, schema.getFixedSize) - case Schema.Type.MAP => Schema.createMap(overrideNamespace(schema.getValueType, namespace)) + case Schema.Type.MAP => Schema.createMap(overrideNamespace(schema.getValueType, namespace)) case Schema.Type.ARRAY => Schema.createArray(overrideNamespace(schema.getElementType, namespace)) - case _ => schema + case _ => schema } } } diff --git a/avro4s-core/src/test/scala/com/sksamuel/avro4s/schema/EnumSchemaTest.scala b/avro4s-core/src/test/scala/com/sksamuel/avro4s/schema/EnumSchemaTest.scala index a184dbaa..93c1983d 100644 --- a/avro4s-core/src/test/scala/com/sksamuel/avro4s/schema/EnumSchemaTest.scala +++ b/avro4s-core/src/test/scala/com/sksamuel/avro4s/schema/EnumSchemaTest.scala @@ -1,6 +1,6 @@ package com.sksamuel.avro4s.schema -import com.sksamuel.avro4s.{AvroEnumDefault, AvroName, AvroNamespace, AvroProp, AvroSchema, AvroSortPriority, JavaEnumSchemaFor, ScalaEnumSchemaFor, SchemaFor} +import com.sksamuel.avro4s.{AvroEnumDefault, AvroName, AvroNamespace, AvroProp, AvroSchema, AvroSortPriority, AvroUnionPosition, JavaEnumSchemaFor, ScalaEnumSchemaFor, SchemaFor} import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec @@ -776,6 +776,37 @@ class EnumSchemaTest extends AnyWordSpec with Matchers { schema.toString(true) shouldBe expected.toString(true) } + + "changing enum namespace should preserve defaults" in { + val schema = AvroSchema[Bowl] + val expected = new org.apache.avro.Schema.Parser().parse( + """ + { + "type": "record", + "name": "Bowl", + "namespace": "com.fruit", + "fields": [ + { + "name": "fruit", + "type": { + "type": "enum", + "name": "Fruit", + "namespace": "com.fruit.bowl", + "symbols": [ + "Unknown", + "Orange", + "Mango" + ], + "default": "Unknown" + }, + "default": "Mango" + } + ] + } + """ + ) + schema.toString(true) shouldBe expected.toString(true) + } } } @@ -800,3 +831,13 @@ sealed trait CupcatAnnotatedEnum @AvroSortPriority(0) case object SnoutleyAnnotatedEnum extends CupcatAnnotatedEnum @AvroSortPriority(1) case object CuppersAnnotatedEnum extends CupcatAnnotatedEnum +@AvroEnumDefault(Unknown) +@AvroNamespace("com.default.package") +sealed trait Fruit + +@AvroUnionPosition(0) case object Unknown extends Fruit +@AvroUnionPosition(1) case object Orange extends Fruit +@AvroUnionPosition(2) case object Mango extends Fruit + +@AvroNamespace("com.fruit") +case class Bowl(@AvroNamespace("com.fruit.bowl") fruit: Fruit = Mango) \ No newline at end of file