Skip to content

Instantly share code, notes, and snippets.

@ubourdon
Last active November 12, 2021 08:21
Show Gist options
  • Save ubourdon/0d9bb30990c7ebee2427b0f9ab16f070 to your computer and use it in GitHub Desktop.
Save ubourdon/0d9bb30990c7ebee2427b0f9ab16f070 to your computer and use it in GitHub Desktop.
example sealed trait zio json
sealed trait UserFilterRight
object UserFilterRight {
case object FilterByMyUid extends UserFilterRight
case class FilterByUser(users: Seq[SafeUUID]) extends UserFilterRight
case object AllInCabinet extends UserFilterRight
case object CanSeeNothing extends UserFilterRight
}
/**
I need to encode and deocde with discriminator e.g
{ "rightType": "FilterByUser"
, "users": [ "12345" ]
}
BUT without using @jsonDiscriminator annotation
*/
@araknafobia
Copy link

It compiles but haven't tried it. It might need a bit clean up - I just came up with it in few minutes.

  sealed trait UserFilterRight
  object UserFilterRight {
    case object FilterByMyUid extends UserFilterRight
    case class FilterByUser(users: Seq[UUID]) extends UserFilterRight
    object FilterByUser {
      implicit val codec: JsonCodec[FilterByUser] = DeriveJsonCodec.gen[FilterByUser]
    }
    case object AllInCabinet extends UserFilterRight
    case object CanSeeNothing extends UserFilterRight

    val userFilterRightDecoder: JsonDecoder[UserFilterRight] = JsonDecoder[Obj].map { userFilterRight =>
      userFilterRight.get(JsonCursor.field("what_am_i").isString) match {
        case Right(Json.Str("FilterByMyUid")) => FilterByMyUid
        case Right(Json.Str("AllInCabinet"))  => AllInCabinet
        case Right(Json.Str("CanSeeNothing")) => CanSeeNothing
        case Right(Json.Str("FilterByUser")) =>
          FilterByUser.codec.decoder.decodeJson(userFilterRight.toJson) match {
            case Left(value)  => ??? // ToDo
            case Right(value) => value
          }
        case _ => ??? // ToDo
      }
    }
    val userFilterRightEncoder: JsonEncoder[UserFilterRight] = JsonEncoder[Json].contramap {
      case FilterByMyUid => Json.Obj.apply("what_am_i" -> Json.Str("FilterByMyUid"))
      case filterByUser @ FilterByUser(_) =>
        val value: Either[String, Json] = FilterByUser.codec.encoder.toJsonAST(filterByUser)
        val u: Json                     = value.getOrElse(Json.Obj()) // ToDo
        val p: Json                     = Json.Obj.apply(("what_am_i" -> Json.Str("FilterByUser")))
        u.merge(p)
      case AllInCabinet  => Json.Obj.apply("what_am_i" -> Json.Str("AllInCabinet"))
      case CanSeeNothing => Json.Obj.apply("what_am_i" -> Json.Str("CanSeeNothing"))
    }

  }

@ubourdon
Copy link
Author

Thx a lot. It help me a lot.

@wadouk
Copy link

wadouk commented Nov 12, 2021

Or with a DTO ?

case class UserFilterRightDTO(rightFilter: String, users: Option[Seq[String]])

a codec on it
a pattern matching on results to encode or decode to UserFilterRight ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment