Open muuki88 opened 5 years ago
Really appreciate for providing this great tool.
Wonder what's the current status of this issue?
I have been working on generating query models from a schema with union type Actor of two subtypes Human and Organization, but the generated code is complaining about missing encoder and failed the application at compile time,
And, I was using CirceJsonCodeGen in my project, looks like the implementation of the encoder generation for union type is not there, wonder if this is intentional and if there are some alternatives to deal with union type query generation from schema?
schemas I used
union Actor = Human | Organization
query Schedules(...) {
schedules(...) {
actor {
__typename
... on Human {
firstname
lastname
}
... on Organization {
orgname
}
}
}
}
looks like the implementation of the encoder generation for union type is not there, wonder if this is intentional and if there are some alternatives to deal with union type query generation from schema?
On the client-side Encoder
for unions is probably useless as GraphQL doesn't support union-types in arguments (at least that was the case a year ago).
The query example you posted would need a Decoder
instance for the actor
so it can decode it for all cases of the union. (based on __typename
as a discriminator).
edit: I think this PR is only about unions in fragments. If you don't use fragments, it is probably already supported.
Fragments are really really nasty and complex for this niche project :sweat:
However you can now override types and specify your own if the plugin does not generate proper code. See the 0.16.0 release notes
@felixbr The query example you posted would need a Decoder instance for the actor so it can decode it for all cases of the union. (based on __typename as a discriminator).
I agree that such encoder for union type is not helpful, but in this case, the derived Encoder of Schedules requires an instance of the Actor encoder to be present to complete the encoder hierarchy, otherwise missing the instance triggers compile error
The generated code.
case class Schedules(...otherArguments, actor: Option[Schedules.Actor])
object Schedules {
implicit val jsonDecoder: Decoder[Schedules] = deriveDecoder[Schedules]
implicit val jsonEncoder: Encoder[Schedules] = deriveEncoder[Schedules]
sealed trait Actor { def __typename: String }
object Actor {
case class Human(__typename: String, firstname: Option[String], lastname: Option[String]) extends Actor
object Human {
implicit val jsonDecoder: Decoder[Human] = deriveDecoder[Practitioner]
implicit val jsonEncoder: Encoder[Human] = deriveEncoder[Practitioner]
}
case class Organization(__typename: String, orgname: Option[String]) extends Actor
object Organization {
implicit val jsonDecoder: Decoder[Organization] = deriveDecoder[Organization]
implicit val jsonEncoder: Encoder[Organization] = deriveEncoder[Organization]
}
implicit val jsonDecoder: Decoder[Actor] = for (typeDiscriminator <- Decoder[String].prepare(_.downField("__typename")); value <- typeDiscriminator match {
//missing encoder for Actor
}
...otherArguments
}
This is the error I have after "sbt compile"
[error] .../code/vcdo-scheduling/web/target/scala-2.13/src_managed/main/sbt-graphql/Schedules.scala:51:67: could not find Lazy implicit value of type io.circe.generic.encoding.DerivedAsObjectEncoder[graphql.codegen.Schedules.Schedules.Schedules]
[error] implicit val jsonEncoder: Encoder[Schedules] = deriveEncoder[Schedules]
@muuki88 thanks for the suggestion, using my own type really solved the issue!