Skip to content

Scala 3: incosistent behavior of Decoder for sealed traits in presence of additional fields. #2368

@kamilkloch

Description

@kamilkloch
import io.circe.literal.*
import io.circe.generic.semiauto.deriveDecoder

object TestCirceScala3 extends App {
  sealed trait Case

  object Case {
    case class C1(b: Int) extends Case

    case class C2(a: String) extends Case

    implicit val decoder: io.circe.Decoder[Case] = deriveDecoder
  }

  println(json"""{"C2" : {"a" : "", "extraFieldC2":  true}}""".as[Case]) // (1)
  println(json"""{"C2" : {"a" : "", "extraFieldC2":  true}, "extraField" : ""}""".as[Case]) // (2)
  println(json"""{"extraField" : "", "C2" : {"a" : "", "extraFieldC2":  true}}""".as[Case]) // (3)
}

prints

Right(C2())
Right(C2())
Left(DecodingFailure at .extraField: type Case has no class/object/case named 'extraField'.)

In (1) C2 is correctly decoded (extraFieldC2 is ignored).
Same for (2), where the decoding stops before reaching extraField.
In (3) decoding fails.
The only difference between the inputs of (2) and (3) is the ordering of the fields in the Json object.

Expected behavior: (3) should decode as Right(C2()). This is what happens in Scala 2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions