简体   繁体   English

Http4s circe 无法解码孩子

[英]Http4s circe can not decode children

I have error model like:我有错误 model 像:

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

in my route I generate http error type based on this model ie:在我的路线中,我根据此 model 生成 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(_)
        )

but problem is that I need to add this asInstanceOf, otherwise circe does not see encoder.但问题是我需要添加这个 asInstanceOf,否则 circe 看不到编码器。 My encoder looks like:我的编码器看起来像:

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

is there a way to avoid doing asInstanceOf there?有没有办法避免在那里做 asInstanceOf ?

You can't use encoder for HttpError for it's subclasses, because Encoder is invariant (it would work if it would be covariant).您不能将编码器用于HttpError的子类,因为Encoder是不变的(如果它是协变的,它将起作用)。

One solution you could use is to define encoder using parametrized def instead of val :您可以使用的一种解决方案是使用参数化def而不是val定义编码器:

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

This way you'd have instance of encoder for all subtypes of HttpError as well as for HttpError .这样,您将拥有 HttpError 的所有子类型以及HttpError的编码器HttpError

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM