Search code examples
scalacirce

How to create a decoder for an Either type with Circe?


If you are expecting to receive either a Json of a type A or type B (Either[A, B]), how could you write a decoder for it?

For example, let's say you are building a client for an external API that can answer with some expected Json structure:

{
  "fieldA": "value",
  "fieldB": "value2"
}

or if something fails, it will answer with an object with an error field:

{
  "error": "Your request was wrong"
}

And then you want to have an instance with either of those structures:

val response: String = // Response from the server 
val decodedValue =
  decode[Either[ErrorResponse, ExpectedResponse](response) // (...) <- What implicit to place here?

How can you write a decoder for either one response structure or the other?


Solution

  • From Circe issue 672, you can write a generic decoder for Either in the following way:

    implicit def eitherDecoder[A, B](implicit a: Decoder[A], b: Decoder[B]): Decoder[Either[A, B]] = {
      val left:  Decoder[Either[A, B]]= a.map(Left.apply)
      val right: Decoder[Either[A, B]]= b.map(Right.apply)
      left or right
    }
    

    Note: For this approach, you still need to implicitly define a decoder for A and for B. In most cases, using deriveDecoder is enough.