Scala Http4s circe无法解码子级

Scala Http4s circe无法解码子级,scala,circe,http4s,http4s-circe,Scala,Circe,Http4s,Http4s Circe,我有如下错误模型: sealed trait HttpError { val msg: String val cause: String } final case class HttpDecodingError(cause: String) extends HttpError { override val msg: String = "Decoding error" } final case class HttpInternalSe

我有如下错误模型:

sealed trait HttpError {
    val msg: String
    val cause: String
  }

  final case class HttpDecodingError(cause: String) extends HttpError {
    override val msg: String = "Decoding error"
  }

  final case class HttpInternalServerError(msg: String, cause: String) extends HttpError
  case object HttpUnauthorizedError extends HttpError {
    override val msg: String = "Invalid credentials"
    override val cause: String = ""
  }
  final case class HttpBadRequestError(msg: String, cause: String) extends HttpError
在我的路由中,我根据以下模型生成http错误类型:

.foldM(
          {
            case error: HttpDecodingError       => BadRequest(error.asInstanceOf[HttpError])
            case error: HttpInternalServerError => InternalServerError(error.asInstanceOf[HttpError])
            case HttpUnauthorizedError          => Unauthorized(withChallenge("Invalid credentials"))
            case error: HttpBadRequestError     => BadRequest(error.asInstanceOf[HttpError])
          },
          Ok(_)
        )
但问题是,我需要将此添加为INSTANCEOF,否则circe看不到编码器。 我的编码器看起来像:

implicit val encodeHttpError: Encoder[HttpError] = (error: HttpError) =>
    Json.obj(("msg", Json.fromString(error.msg)), ("cause", Json.fromString(error.cause)))

有没有一种方法可以避免对其进行安装?

您不能对其子类使用encoder for
HttpError
,因为
encoder
是不变的(如果它是协变的,它会起作用)

您可以使用的一种解决方案是使用参数化的
def
而不是
val
定义编码器:

implicit def encodeHttpError[E <: HttpError]: Encoder[E] = (error: E) =>
  Json.obj(
    ("msg", Json.fromString(error.msg)),
    ("cause", Json.fromString(error.cause))
  )
隐式def encodeHttpError[E
Json.obj(
(“msg”,Json.fromString(error.msg)),
(“原因”,Json.fromString(error.cause))
)

通过这种方式,您可以为
HttpError
的所有子类型以及
HttpError

创建编码器实例,您不能将编码器用于
HttpError
的子类,因为
encoder
是不变的(如果它是协变的,它就会工作)

您可以使用的一种解决方案是使用参数化的
def
而不是
val
定义编码器:

implicit def encodeHttpError[E <: HttpError]: Encoder[E] = (error: E) =>
  Json.obj(
    ("msg", Json.fromString(error.msg)),
    ("cause", Json.fromString(error.cause))
  )
隐式def encodeHttpError[E
Json.obj(
(“msg”,Json.fromString(error.msg)),
(“原因”,Json.fromString(error.cause))
)
这样,您就可以为
HttpError
的所有子类型以及
HttpError
创建编码器实例