如何使用 Circe 为 Either 类型创建解码器?

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

如果您希望收到类型为 A 或类型为 B (Either[A, B]) 的 Json,您如何为它编写解码器?

例如,假设您正在为外部 API 构建一个客户端,它可以用一些预期的 Json 结构来回答:

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

或者如果出现问题,它将用一个带有 error 字段的对象来回答:

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

然后你想要一个具有这些结构之一的实例:

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

如何为一种或另一种响应结构编写解码器?

Circe issue 672开始,您可以通过以下方式为 Either 编写通用解码器:

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
}

注意:对于这种方法,您仍然需要为AB隐式定义一个解码器。在大多数情况下,使用 deriveDecoder 就足够了。