Search code examples
scalaavro

Avro to Scala case class annotation with nested types


I am using Avro serialization for messages on Kafka and processing with some custom Scala code using this annotation method currently. The following is a basic schema with a nested record:

{
  "type": "record",
  "name": "TestMessage",
  "namespace": "",
  "fields": [
    {"name": "message", "type": "string"},
    {
      "name": "metaData",
      "type": {
        "type": "record",
        "name": "MetaData",
        "fields": [
          {"name": "source", "type": "string"},
          {"name": "timestamp", "type": "string"}
        ]
      }
    }
  ]
}

And the annotation, I believe should quite simply look like:

@AvroTypeProvider("schema-common/TestMessage.avsc")
@AvroRecord
case class TestMessage()

The message itself is something like the following:

{"message":"hello 1",
 "metaData":{
   "source":"postman",
   "timestamp":"123456789"
 }
}

However when I log the TestMessage type or view the output in a Kafka consumer in the console, all I see is:

{"message":"hello 1"}

And not the subtype I added to capture MetaData. Anything I am missing? Let me know if I can provide further information - thanks!


Solution

  • This should now be fixed in version 0.10.3 for Scala 2.11, and version 0.4.5 for scala 2.10

    Keep in mind that for every record type in a schema, there needs to be a case class that represents it. And for Scala 2.10, the most nested classes must be defined first. A safe definition is the following:

    @AvroTypeProvider("schema-common/TestMessage.avsc")
    @AvroRecord
    case class MetaData()
    
    @AvroTypeProvider("schema-common/TestMessage.avsc")
    @AvroRecord
    case class TestMessage()