Кодировщик Circe для универсального класса case с параметрами по умолчанию

Я хочу предоставить кодировщики JSON для следующего класса case:

import io.circe.generic.extras.Configuration

final case class Hello[T](
    source: String, 
    version: Int = 1,
    data: T
)

object Hello {
  implicit val configuration: Configuration = Configuration.default.withDefaults
}

Обычно я бы вызвал deriveEncoder[A] в сопутствующем объекте, но здесь это не работает, поскольку здесь нет ссылки или Encoder для T.

Тип Hello будет предоставляться клиентам как библиотека, поэтому я хотел бы сделать как можно больше шаблонов в этом типе, а не зависеть от клиентского кода, предоставляющего кодировщик и декодер. Есть ли идиоматическое решение этой проблемы с помощью circe, чтобы клиенты предоставляли кодировщик / декодер для T, и это используется для получения кодировщика / декодера для Hello[T]?


person Rich Ashworth    schedule 28.01.2019    source источник


Ответы (1)


Да, вам нужно добавить контекстную привязку, требующую наличия неявного кодировщика для любого типа T:

import io.circe.gemeric.semiauto._

final case class Hello[T](
  source: String,
  version: Int = 1,
  data: T
)

object Hello {
  implicit def helloEncoder[T: Encoder]: Encoder[Hello[T]] = deriveEncoder
}

Таким образом, когда пользователь создает свой собственный тип Hello[Foo], он должен будет убедиться, что Foo имеет собственный кодировщик.

person Yuval Itzchakov    schedule 28.01.2019
comment
Это правильный ответ. @Rich, обратите внимание, что часть, в которой вы говорите, зависит от клиентского кода, предоставляющего кодировщик и декодер, не может быть выполнена; в решении Yuval они по-прежнему должны предоставить кодировщик. Если вы хотите, чтобы у них была свобода выбора своего собственного Т, это цена, которую нужно заплатить. - person slouc; 28.01.2019