【问题标题】:Http4s circe can not decode childrenHttp4s circe 无法解码孩子
【发布时间】:2021-04-24 16:12:56
【问题描述】:

我有如下错误模型:

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(_)
        )

但问题是我需要添加这个 asInstanceOf,否则 circe 看不到编码器。 我的编码器看起来像:

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

有没有办法避免在那里做 asInstanceOf ?

【问题讨论】:

    标签: scala circe http4s http4s-circe


    【解决方案1】:

    您不能将编码器用于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))
      )
    

    这样,您将拥有HttpError 以及HttpError 的所有子类型的编码器实例。

    【讨论】:

      猜你喜欢
      • 2017-06-12
      • 2020-05-03
      • 2020-09-26
      • 2020-07-06
      • 2017-05-24
      • 2017-08-21
      • 2017-11-27
      • 2019-03-15
      • 1970-01-01
      相关资源
      最近更新 更多