Inconsistent encoding/decoding of nested sum types
matil019 opened this issue · comments
As of 0.14.5, derived encoder and decoder of a nested sum type are inconsistent. The Decoder
can't decode a JSON encoded by the Encoder
.
Minimal example:
import io.circe.Decoder
import io.circe.Encoder
import io.circe.generic.semiauto.deriveDecoder
import io.circe.generic.semiauto.deriveEncoder
import io.circe.parser.decode
import io.circe.syntax._
sealed trait Top
object Top {
sealed trait Middle extends Top
object Middle {
case object Bottom extends Middle
}
implicit val decodeTop: Decoder[Top] = deriveDecoder
implicit val encodeTop: Encoder[Top] = deriveEncoder
}
object Main {
def main(args: Array[String]): Unit = {
val s = (Top.Middle.Bottom: Top).asJson.noSpaces
println(s)
println(decode[Top](s))
}
}
Expected output (scala:3.2.2, circe:0.14.3)
{"Middle":{"Bottom":{}}}
Right(Bottom)
Actual output (scala:3.2.2, circe:0.14.5)
{"Middle":{"Bottom":{}}}
Left(DecodingFailure at .Middle: type Top has no class/object/case named 'Middle'.)
^ In this case, the decoder can decode {"Bottom":{}}
to Bottom
.
It turned out that both of the above are also inconsistent with scala 2.13 build of circe:
Output (scala:2.13.0, circe:0.14.3/0.14.5)
{"Bottom":{}}
Right(Bottom)
So I'm not sure which encoding is correct.
I would expect the Scala 2 output, not the Scala 3 output.
Seems like this relates to / was introduced by #2098 (I didn't look into the code changes (yet), but did test before / after that commit).
Found a fix for the inconsistency.
(I do agree that the encoded json should be the same as for Scala 2, but fixing that is beyond what I'm currently able to contribute.)
(I do agree that the encoded json should be the same as for Scala 2, but fixing that is beyond what I'm currently able to contribute.)
Nevermind - found a better way to fix the inconsistency that also fixes the encoding to {"Bottom":{}}
.