Универсальная функция Scala... с использованием T в функции

Я немного запутался, почему приведенный ниже код не работает:

  implicit val connectReads: Reads[ConnectCommand] = (
    (JsPath \ "uuid").read[String]
    )(ConnectCommand.apply _)

  private def generateMessage[T](json: JsValue) = json.validate[T] match {
    case s: JsSuccess[T] => s.asOpt
    case e: JsError => None
  }

Функция будет вызываться следующим образом:

generateMessage[ConnectCommand](json)

Я получаю следующие ошибки:

Error:(59, 64) No Json deserializer found for type T. Try to implement an implicit Reads or Format for this type.
  private def generateMessage[T](json: JsValue) = json.validate[T] match {
                                                               ^
Error:(59, 64) not enough arguments for method validate: (implicit rds: play.api.libs.json.Reads[T])play.api.libs.json.JsResult[T].
Unspecified value parameter rds.
  private def generateMessage[T](json: JsValue) = json.validate[T] match {
                                                           ^

Я довольно новичок в дженериках Scala... есть ли способ сделать то, что я пытаюсь сделать здесь?

2 ответа

Решение

Согласно документации JsValue.validate требует неявного Reads чтобы ваш тип был доступен:

def validate[T](implicit rds: Reads[T]): JsResult[T] 

Предполагая, что он у вас есть в том месте, куда вы звоните generateMessage от, вы должны передать его в generateMessage, чтобы validate увидит это также:

private def generateMessage[T](json: JsValue)(implicit rds: Reads[T])

или более короткая форма:

private def generateMessage[T : Reads](json: JsValue)

Это на самом деле не связано с обобщениями, а скорее с последствиями и тем, как библиотеки требуют, чтобы вы определяли типы последствий и импортировали их.

Это необходимо, потому что validate функция не знает формат вашего JsValue поэтому требует implicit scope предоставить один. Затем он использует формат для проверки. Поначалу это сбивает с толку, но в конечном итоге приятнее, потому что вам не нужно явно указывать формат для каждого вызова метода, когда требуется формат JSON.

Также это две строки, которые выдают это в сообщении об ошибке:

Try to implement an implicit Reads or Format for this type.

not enough arguments for method validate: (implicit rds: play.api.libs.json.Reads[T])

Мы видим, что вам нужно либо импортировать неявный Format / Reads или определите себя. О том, как это сделать, вы можете прочитать в соответствующем разделе Play! документация

РЕДАКТИРОВАТЬ:

В вашем методе отсутствует неявный параметр (implicit reads: Reads[T]) передать его validate функция:

private def generateMessage[T](json: JsValue)(implicit reads: Reads[T]) = json.validate[T] match {
 case s: JsSuccess[T] => s.asOpt
 case e: JsError => None
}
Другие вопросы по тегам