Scala, cats - конвертируйте FUUID с помощью 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. У меня также есть routes, созданный с Http4s, который должен принимать 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
   }
}

Я также добавил несколько implicits для кодирования и декодирования из Circe:

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]
}

Проблема в том, что когда я хочу скомпилировать проект, я получаю такие ошибки в классе маршрута:

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 на Long, а после этого только на UUID java, а затем все правильно компилируется без ошибок. Проблема только в FUUID и, вероятно, в его преобразовании. Я пробовал использовать Circe Integration, как показано в ссылке FUUID выше, но это не помогло. Вы знаете, как исправить этот код, чтобы все скомпилировать с fuuid и circe? Я новичок в cats и связанных библиотеках, так что, возможно, это простая ошибка, но сейчас для меня это нетривиально.


person Developus    schedule 21.04.2019    source источник


Ответы (1)


Чтобы иметь EntityDecoder[F, Bet] через jsons.circeDecoder, нам сначала понадобится Decoder[Bet]. Он может быть автоматически сгенерирован Цирцеей, если у нас есть декодеры для всех полей. Дело в том, что 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)
person Dmytro Mitin    schedule 21.04.2019
comment
Наверное encoder тоже нужна? Я добавил этот, но все еще возникают ошибки, связанные с кодировщиком: Cannot convert from model.Bet to an Entity, because no EntityEncoder[F, model.Bet] instance could be found. response <- Created(created) - person Developus; 21.04.2019
comment
и еще один вопрос: зачем использовать Decoder[UUID]? Как я вижу, это java uuid, но я использую FUUID или это другой тип uuid? - person Developus; 21.04.2019
comment
@allocer Наверное кодировщик тоже нужен? Да, обновил ответ. - person Dmytro Mitin; 21.04.2019
comment
@allocer зачем использовать Decoder[UUID]? Потому что у вас есть это неявное, но вам нужно неявное Decoder[FUUID]. - person Dmytro Mitin; 21.04.2019