0
sealed trait FormField 
case class StringField(name: String, value: String) extends FormField 
case class ChoiceField[T : Writes](name: String, value: T, choices: List[T]) extends FormField 

, а затем, где-то еще мне нужно сделать, это:Scala шаблон матч с параметром типа класса типа

def makeJson(fields: List[FormField]) = fields.map { 
    case StringField(name, value) => Json.obj(name -> value) 
    case ChoiceField(name, value, _) => Json.obj(name -> value) 
} 

В этой последней функции, scalac/SBT «не понимает», что value является преобразуется в json (через его неявный/тип-класс Writes[T]). Как я могу написать его так, чтобы он «получил»?

(Примечание: Writes[T] от Play Framework - это в основном говорит, что существует неявное преобразование доступна для типа T => JsValue)

+0

:

case class ChoiceField[T](name: String, value: T, choices: List[T])(implicit val writes: Writes[T]) extends FormField 

и вашего шаблона матча «Нет Json сериализатора найден для типа Any не пытаться реализовать неявный пишущие или формат для этого типа.». – kornfridge

+0

Можете ли вы создать экземпляр 'Writer [FormField]', который может превратить 'StringField' или' ChoiceField' в json? –

+0

Если я попытался создать 'Writes [FormField]', мне все равно понадобилось бы сопоставить шаблон, и у меня была бы такая же проблема. (EDIT: 'makeJson' здесь _is_ в основном' Writes [FormField] ') – kornfridge

ответ

3

Ваша проблема заключается в том, что Writes неявное не в рамках, когда вы делаете поиск по шаблону; самым простым решением было бы иметь ясную ссылку на него, чтобы вы могли использовать его, когда это необходимо. Таким образом, ваше определение класса становится чем-то вроде:

case cf @ ChoiceField(name, value, _) => 
    implicit val tWrites = cf.writes 
    Json.obj(name -> value) 
+0

Это работает. Спасибо! – kornfridge

+0

Хм. Я нарушаю обычные «правила» классов случаев здесь? Теперь класс case имеет два списка параметров, и записи вовсе не предназначены для «соответствия шаблону». Этот неприятный код ...? Что еще я могу сделать? – kornfridge

+1

Я не думаю, что здесь существует какое-либо нарушение правил: граница контекста, определенная как '[T: Writes]', является просто синтаксическим сахаром для неявного параметра; если вы захотели, вы могли бы написать его как «класс case ChoiceField [T: Writes] (name: String, value: T, choice: List [T]) {lazy val пишет = неявно [Writes [T]]}', но в конце концов, это одно и то же. Честно говоря, я, наверное, недостаточно разбираюсь в игре, чтобы придумать что-то более умное, чем это. –

Смежные вопросы