Этот пример будет работать в данном конкретном случае:
import org.scalatest.{Matchers, WordSpecLike}
object O {
import spray.json._
import spray.json.DefaultJsonProtocol._
sealed trait Base[K, V]
case class Foo[K, V](key: K, value: V) extends Base[K, V]
case class Bar[K, V](key: V, value: K) extends Base[K, V]
implicit def fooJsonConvertor[K: JsonFormat, V: JsonFormat] = jsonFormat2(Foo.apply[K, V])
implicit def barJsonConvertor[K: JsonFormat, V: JsonFormat] = jsonFormat2(Bar.apply[V, K])
implicit def baseJsonConvertor[K: JsonFormat: Manifest, V: JsonFormat: Manifest] = new JsonFormat[Base[K, V]] {
override def read(json: JsValue): Base[K, V] =
throw new SerializationException("Don't use this for reading...")
override def write(obj: Base[K, V]): JsValue = obj match {
case e@Foo(_: K, _: V) => implicitly[JsonFormat[Foo[K,V]]].write(e.asInstanceOf[Foo[K, V]])
case e@Bar(_: V, _: K) => implicitly[JsonFormat[Bar[K,V]]].write(e.asInstanceOf[Bar[K, V]])
}
}
}
class Spec extends WordSpecLike with Matchers {
import O._
import spray.json._
import spray.json.DefaultJsonProtocol._
"test" should {
"test" in {
val list = List[Base[String, Int]](Foo[String, Int]("One", 1), Bar(2, "Two")).map(_.toJson)
println(list)
}
}
}
Однако вы не можете использовать Base без параметров типа, потому что вы не сможете получить JsonFormat без них.Обратите внимание, что вы должны объявлять незаконные jsonFormats в обратном порядке, который они использовали.Я имею в виду, что вы должны сначала объявить неявное для JsonFormat Foo и Bar, а затем для Base.В противном случае они не смогут быть обнаружены.Вы также должны использовать неявный Manifest, чтобы иметь возможность безопасно сопоставлять.
Если вы действительно получили более сложный случай с переменным количеством параметров типа в дочерних классах, это не сработает для вас.Я не думаю, что случай с переменным числом аргументов будет эффективно разрешен без исключения параметров типа в дочерних классах.Также обратите внимание, что объект O, содержащий импликации, должен быть объявлен перед Spec, если он находится в том же файле, что и Spec, чтобы быть видимым в Spec.