Scala,猫——用 Circe 转换 FUUID

Scala, cats - convert FUUID with Circe

我使用此库 https://christopherdavenport.github.io/fuuid/ 创建 ID 自定义对象并将它们保存到数据库中。 我有一个简单的 case class 这是我的模型:

import io.chrisdavenport.fuuid.FUUID

case class Bet(
  betId: Option[FUUID],
  home: String,
  away: String,
  stake: BigDecimal,
  betType: String)

我在这里使用 FUUID 作为 Option 参数。我还有一个用 Http4s 创建的 routes,它应该从输入中获取 json 并将其映射到模型中:

class BettingRoutes[F[_] : Async](service: BettingService[F]) extends Http4sDsl[F] {

  def routes: HttpRoutes[F] = HttpRoutes.of[F] {
    case req@PUT -> Root / "bets" =>
      for {
        bet <- req.as[Bet]
        created <- service.put(bet)
        response <- Created(created)
      } yield response
   }
}

我还添加了一些 implicitsCirce 进行编码和解码:

object jsons {
  implicit def circeDecoder[A[_] : Sync, B: Decoder]: EntityDecoder[A, B] = jsonOf[A, B]
  implicit def circeEncoder[A[_] : Sync, B: Encoder]: EntityEncoder[A, B] = jsonEncoderOf[A, B]
}

问题是 - 当我想编译项目时,我在路由 class:

中遇到这样的错误
Error:(23, 22) Cannot decode into a value of type model.Bet, because no EntityDecoder[F, model.Bet] instance could be found.
        bet <- req.as[Bet]

Error:(23, 22) not enough arguments for method as: (implicit F: cats.Functor[F], implicit decoder: org.http4s.EntityDecoder[F,model.Bet])F[model.Bet].
Unspecified value parameter decoder.
        bet <- req.as[Bet]

Error:(25, 28) Cannot convert from model.Bet to an Entity, because no EntityEncoder[F, model.Bet] instance could be found.
        response <- Created(created)

等我调查了它,它出现是因为使用了 FUUID。我将所有 FUUID classes 更改为 Long,然后将其更改为 java 的 UUID,然后所有内容都可以正确编译,没有错误。问题仅在于 FUUID 并且可能与它的转换有关。我尝试使用上面 FUUID link 中显示的 Circe Integration,但它没有帮助。您知道如何修复此代码以使用 fuuidcirce 编译所有内容吗? 我是 cats 和连接库的新手,所以这可能是一个简单的错误,但现在对我来说并不是微不足道的。

为了通过jsons.circeDecoder获得EntityDecoder[F, Bet],我们首先需要Decoder[Bet]。如果我们有所有领域的解码器,它可以由 Circe 自动生成。问题是有 Decoder[UUID] 但没有 Decoder[FUUID].

所以只需定义必要的隐式

implicit val fuuidDecoder: Decoder[FUUID] = Decoder[UUID].map(FUUID.fromUUID)

与编码器类似

implicit val fuuidEncoder: Encoder[FUUID] = Encoder[UUID].contramap(FUUID.Unsafe.toUUID)