zio / zio-schema

Compositional, type-safe schema definitions, which enable auto-derivation of codecs and migrations.
https://zio.dev/zio-schema
Apache License 2.0
142 stars 162 forks source link

Avro schema for Option[Enum] failing to decode #608

Closed mattdavpir closed 6 months ago

mattdavpir commented 1 year ago

Hey,

We've tried making a field that was an enum into an Option (i.e. rather than myFIeld: MyEnum it's now myField: Option[MyEnum]) and it seems that when decoding the bytes we enter decodeGenericEnum with an enumCaseName of zio.schema.codec.avro.wrapper_hashed_n1189833338rather than the proper enum name.

Simple example:

object AvroSerde:
  def create[A: Schema]: Serde[Any, A] =
    given BinaryCodec[A] = AvroCodec.schemaBasedBinaryCodec
    Serde.byteArray.inmapM(decodeBytes[A])(encodeA[A])

  private def decodeBytes[A](using codec: BinaryCodec[A]) =
    (bytes: Array[Byte]) => ZIO.fromEither[Throwable, A](codec.decode(Chunk.fromArray(bytes)))

  private def encodeA[A](using codec: BinaryCodec[A]) =
    (a: A) => ZIO.succeed(codec.encode(a).toArray)

object Test extends ZIOAppDefault:
  enum MyEnum:
    case A, B, C

  final case class MyType(id: Long, myEnum: MyEnum)

  final case class MyTypeWithOption(id: Long, myEnum: Option[MyEnum])

  given Schema[MyType] = DeriveSchema.gen[MyType]

  given Schema[MyTypeWithOption] = DeriveSchema.gen[MyTypeWithOption]

  val myTypeSerde = AvroSerde.create[MyType]
  val myTypeWithOptionSerde = AvroSerde.create[MyTypeWithOption]

  val topic = "blah"

  override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] =
    for
      bytes  <- myTypeSerde.serialize(topic, new RecordHeaders(), MyType(123L, MyEnum.B))
      myType <- myTypeSerde.deserialize(topic, new RecordHeaders(), bytes)
      _      <- ZIO.logInfo(myType.toString) // Prints "MyType(123,B)"

      // This serialize throws an exception for me, which is not the error that I'm seeing in my real project beause we 
      // aren't the ones serializing the data, but it looks related
      bytesOption  <- myTypeWithOptionSerde.serialize(topic, new RecordHeaders(), MyTypeWithOption(123L, Some(MyEnum.B)))
      myTypeOption <- myTypeWithOptionSerde.deserialize(topic, new RecordHeaders(), bytesOption)
      _            <- ZIO.logInfo(myType.toString)
    yield ()
jdegoes commented 10 months ago

/bounty $100

algora-pbc[bot] commented 10 months ago

## 💎 $100 bounty • ZIO

### Steps to solve: 1. Start working: Comment /attempt #608 with your implementation plan 2. Submit work: Create a pull request including /claim #608 in the PR body to claim the bounty 3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to zio/zio-schema!

Add a bounty • Share on socials

Attempt Started (GMT+0) Solution
🟢 @pablf #659
algora-pbc[bot] commented 9 months ago

💡 @pablf submitted a pull request that claims the bounty. You can visit your bounty board to reward.

algora-pbc[bot] commented 9 months ago

🎉🎈 @pablf has been awarded $100! 🎈🎊