Skip to content

jsonDiscriminator does not add field when encoding #1197

@funrep

Description

@funrep

When encoding toJson and using @jsonDiscriminator("type") on sealed traits the output string does not have type field as expected. In this example BarNotOk is expected to parse, but does not with error (missing hint 'type').

  • BarNotOk uses derives JsonCodec and is expected to add type field when encoding/decoding, but encoding is not working as expected and the type field is not added when running toJson.
  • BarOk uses a work-around to get the expected behaviour, specifying a custom encoder that explicitly adds the type field. This has the expected behaviour but requires extra work-around code.
scalaVersion := "3.5.0"

libraryDependencies ++= Seq(
  "dev.zio" %% "zio" % "2.0.15",
  "dev.zio" %% "zio-json" % "0.7.3"
)
import zio._
import zio.json._

@jsonDiscriminator("type")
sealed trait Foo derives JsonCodec

@jsonDiscriminator("type")
case class BarOk(bar: Int) extends Foo derives JsonDecoder

@jsonDiscriminator("type")
case class BarNotOk(bar: Int) extends Foo derives JsonCodec

object BarOk:
  given JsonEncoder[BarOk] = JsonEncoder
    .derived[BarEncoder]
    .contramap[BarOk] { case BarOk(bar) =>
      BarEncoder(bar)
    }

case class BarEncoder(bar: Int, `type`: String = "BarOk") derives JsonEncoder

object HelloWorld extends ZIOAppDefault {
  def run =
    val bar1 = BarNotOk(bar = 42)
    val barStr1 = bar1.toJson
    val bar2 = BarOk(bar = 42)
    val barStr2 = bar2.toJson
    for
      _ <- Console.printLine(barStr1)
      _ <- Console.printLine(barStr2)
      _ <- ZIO
        .fromEither(barStr1.fromJson[Foo])
        .flatMap(b => Console.printLine(b.toString))
        .catchAll(e => Console.printLine(e.toString))
      _ <- ZIO
        .fromEither(barStr2.fromJson[Foo])
        .flatMap(b => Console.printLine(b.toString))
        .catchAll(e => Console.printLine(e.toString))
    yield ()
}

Output:

{"bar":42}
{"bar":42,"type":"BarOk"}
(missing hint 'type')
BarOk(42)

Expected output:

{"bar":42,"type":"BarNotOk"}
{"bar":42,"type":"BarOk"}
BarNotOk(42)
BarOk(42)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions