Camilo Sampedro
Camilo Sampedro

Reputation: 1436

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?

Upvotes: 4

Views: 2022

Answers (2)

Matej Cerny
Matej Cerny

Reputation: 73

To slightly simplify the previous answer:

implicit def eitherDecoder[A, B](implicit a: Decoder[A], b: Decoder[B]): Decoder[Either[A, B]] =
  a.either(b)

Upvotes: 1

Camilo Sampedro
Camilo Sampedro

Reputation: 1436

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.

Upvotes: 5

Related Questions