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
141 stars 161 forks source link

Cannot generate schema for sealed trait with enum implementors #697

Closed anqit closed 2 months ago

anqit commented 3 months ago

I'm trying to use zio-schema with zio-http to de/serialize request/response Bodys. I have a sealed trait representing the response body of my API, and two implementors of that trait, both of which are enums, representing success bodies (with a "data" field) and failure bodies (with a "message" field), but cannot seem to generate a schema for this structure. The below scala-cli script is a minimal representation of what I've tried. This compiles but fails at runtime with a ClassCastException:

//> using dep dev.zio::zio:2.1.1
//> using dep dev.zio::zio-http:3.0.0-RC8

import zio.schema.{ DeriveSchema, Schema, TypeId }
import zio.schema.Schema.Sequence
import zio.schema.codec.BinaryCodec
import zio.schema.codec.JsonCodec.schemaBasedBinaryCodec
import zio.http.*

sealed trait HttpResponse[+D]

enum HttpSuccessResponse[+D](val data: D) extends HttpResponse[D]:
   case Created[E](entity: E) extends HttpSuccessResponse[E](entity)
   case Found[E](entity: E) extends HttpSuccessResponse[E](entity)
   case Updated[E](entity: E) extends HttpSuccessResponse[E](entity)
   case Deleted[E](entity: E) extends HttpSuccessResponse[E](entity)
   case Succeeded[E](entity: E) extends HttpSuccessResponse[E](entity)

enum HttpFailureResponse(val message: String) extends HttpResponse[String]:
   case ServerError(msg: String) extends HttpFailureResponse(msg)
   case RequestError(msg: String) extends HttpFailureResponse(msg)

given HttpSuccessResponseSchema[D](using Schema[D]): Schema[HttpSuccessResponse[D]] = DeriveSchema.gen

given HttpFailureResponseSchema: Schema[HttpFailureResponse] = DeriveSchema.gen

given HttpResponseSchema[D](using Schema[D]): Schema[HttpResponse[D]] = DeriveSchema.gen

val response = HttpSuccessResponse.Created("user")

val body = Body.from(response)

@main def run() =
   println(body.asString)

The full error is

Exception in thread "main" java.lang.ExceptionInInitializerError
        at run.main(error_repro.scala:34)
Caused by: java.lang.ClassCastException: class zio.schema.Schema$CaseClass1$$anon$7 cannot be cast to class zio.schema.Schema$CaseClass0 (zio.schema.Schema$CaseClass1$$anon$7 and zio.schema.Schema$CaseClass0 are in unnamed module of loader 'app')
        at zio.schema.codec.JsonCodec$JsonEncoder$.$anonfun$2(JsonCodec.scala:388)
        at zio.Chunk$Arr.mapChunk(Chunk.scala:1769)
        at zio.ChunkLike.map(ChunkLike.scala:121)
        at zio.ChunkLike.map$(ChunkLike.scala:39)
        at zio.Chunk.map(Chunk.scala:42)
        at zio.schema.codec.JsonCodec$JsonEncoder$.enumEncoder(JsonCodec.scala:389)
        at zio.schema.codec.JsonCodec$JsonEncoder$.schemaEncoder(JsonCodec.scala:205)
        at zio.schema.codec.JsonCodec$JsonEncoder$.encode(JsonCodec.scala:177)
        at zio.schema.codec.JsonCodec$$anon$2.encode(JsonCodec.scala:93)
        at zio.schema.codec.JsonCodec$$anon$2.encode(JsonCodec.scala:92)
        at zio.http.Body$.from(Body.scala:209)
        at error_repro$package$.<clinit>(error_repro.scala:13)

Am I just doing this incorrectly or is this something not supported?

anqit commented 3 months ago

potentially related to https://github.com/zio/zio-schema/issues/668 ?

jdegoes commented 3 months ago

/bounty $100

algora-pbc[bot] commented 3 months ago

šŸ’Ž $100 bounty ā€¢ ZIO

Steps to solve:

  1. Start working: Comment /attempt #697 with your implementation plan
  2. Submit work: Create a pull request including /claim #697 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 #707
anqit commented 3 months ago

I'm guessing an assigned bounty means that what I'm trying to do is indeed unsupported at this time? I was hoping I was just doing something wrong...

algora-pbc[bot] commented 3 months ago

šŸ’” @pablf submitted a pull request that claims the bounty. You can visit your bounty board to reward.

algora-pbc[bot] commented 2 months ago

šŸŽ‰šŸŽˆ @pablf has been awarded $100! šŸŽˆšŸŽŠ