zio / zio-json

Fast, secure JSON library with tight ZIO integration.
https://zio.dev/zio-json
Apache License 2.0
410 stars 146 forks source link

what is the intended semantics for encoding case objects? #196

Open cartazio opened 3 years ago

cartazio commented 3 years ago

i'm having a hard time finding info in the tests etc :)

cartazio commented 3 years ago

context: i've got some examples where the withNameOption style of enum encoding is what i want, and it looks like the current zio-json default is essentially the tag:{} rep. which seems like an odd choice efficiency wise :)

fsvehla commented 3 years ago

The @jsonDiscriminator example from the Readme also applies to case objects, is this what you’re looking for?

test("cartazio0") {
  @jsonDiscriminator("type")
  sealed trait Fruit

  object Fruit {
    case object Avocado extends Fruit
    case object Banana  extends Fruit
    case object Tomato  extends Fruit

    implicit val encoder: JsonEncoder[Fruit] = DeriveJsonEncoder.gen[Fruit]
    implicit val decoder: JsonDecoder[Fruit] = DeriveJsonDecoder.gen[Fruit]
  }

  assert((Fruit.Avocado: Fruit).toJson)(equalTo("""{"type":"Avocado"}""")) &&
  assert("""{"type": "Avocado"}""".fromJson[Fruit])(equalTo(Right(Fruit.Avocado)))
}
cartazio commented 3 years ago

so in my case, the behavior i'm wanting/doing is the one you'd get from something like

implicit val decoder: JsonDecoder[Gender] = implicitly[JsonDecoder[String]].mapOrFail(x => Gender.withNameEither(x).leftMap(y => y.getMessage))
implicit val encoder: JsonEncoder[Gender] = implicitly[JsonEncoder[String]].contramap(_.toString())

this is partly cause of keeping compatibility with an existing API. And i guess i'm just slightly surprised that ZIO doesnt choose the more succinct choice in this case

this example is using the withNameEither operation via enumeratum package