Skip to content

Commit

Permalink
Added set/list support to reflection schema builder
Browse files Browse the repository at this point in the history
  • Loading branch information
sksamuel committed Apr 14, 2024
1 parent b6c8514 commit 67f9893
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.sksamuel.centurion.avro.generation
import org.apache.avro.Schema
import org.apache.avro.SchemaBuilder
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.full.memberProperties

class ReflectionSchemaBuilder {
Expand All @@ -13,26 +14,29 @@ class ReflectionSchemaBuilder {

val builder = SchemaBuilder.record(kclass.java.name).namespace(kclass.java.packageName)
return kclass.memberProperties.fold(builder.fields()) { acc, op ->

val typeBuilder = if (op.returnType.isMarkedNullable)
SchemaBuilder.nullable()
else
SchemaBuilder.builder()

val type = when (val classifier = op.returnType.classifier) {
String::class -> typeBuilder.stringType()
Boolean::class -> typeBuilder.booleanType()
Int::class -> typeBuilder.intType()
Long::class -> typeBuilder.longType()
Short::class -> typeBuilder.intType()
Byte::class -> typeBuilder.intType()
Double::class -> typeBuilder.doubleType()
Float::class -> typeBuilder.floatType()
else -> error("Unsupported type $classifier")
}

acc.name(op.name).type(type).noDefault()
acc.name(op.name).type(schemaFor(op.returnType)).noDefault()
}.endRecord()
}

private fun schemaFor(type: KType): Schema {

val typeBuilder = if (type.isMarkedNullable)
SchemaBuilder.nullable()
else
SchemaBuilder.builder()

return when (val classifier = type.classifier) {
String::class -> typeBuilder.stringType()
Boolean::class -> typeBuilder.booleanType()
Int::class -> typeBuilder.intType()
Long::class -> typeBuilder.longType()
Short::class -> typeBuilder.intType()
Byte::class -> typeBuilder.intType()
Double::class -> typeBuilder.doubleType()
Float::class -> typeBuilder.floatType()
Set::class -> typeBuilder.array().items(schemaFor(type.arguments.first().type!!))
List::class -> typeBuilder.array().items(schemaFor(type.arguments.first().type!!))
else -> error("Unsupported type $classifier")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import org.apache.avro.SchemaBuilder

data class Foo1(val a: String, val b: Boolean, val c: Long)
data class Foo2(val a: String?, val b: Boolean, val c: Long)
data class Foo3(val set1: Set<Int>, val set2: Set<Int?>)
data class Foo4(val list1: List<Int>, val list2: List<Int?>)

class ReflectionSchemaBuilderTest : FunSpec({

Expand All @@ -29,4 +31,22 @@ class ReflectionSchemaBuilderTest : FunSpec({
ReflectionSchemaBuilder().schema(Foo2::class) shouldBe expected
}

test("sets") {
val expected = SchemaBuilder.record("Foo3").namespace(Foo3::class.java.packageName)
.fields()
.name("set1").type(SchemaBuilder.array().items().intType()).noDefault()
.name("set2").type(SchemaBuilder.array().items(SchemaBuilder.nullable().intType())).noDefault()
.endRecord()
ReflectionSchemaBuilder().schema(Foo3::class) shouldBe expected
}

test("lists") {
val expected = SchemaBuilder.record("Foo4").namespace(Foo4::class.java.packageName)
.fields()
.name("list1").type(SchemaBuilder.array().items().intType()).noDefault()
.name("list2").type(SchemaBuilder.array().items(SchemaBuilder.nullable().intType())).noDefault()
.endRecord()
ReflectionSchemaBuilder().schema(Foo4::class) shouldBe expected
}

})

0 comments on commit 67f9893

Please sign in to comment.