Play Framework提供了一种通过隐式Writes
将对象转换为JSON的方法。
def toJson[T](o: T)(implicit tjs: Writes[T]): JsValue
我有一个处理消息的部分函数,如果存在Writes,其中一些可以序列化为JSON。如何编写与存在隐式Writes的对象匹配的案例?
override def receive = {
case obj:/*(T where there exists an implicit Writes[T])*/ =>
return Json.toJson(obj)
case other =>
return Json.obj("unknown" -> other.toString)
}
基本上我想要的是
的缩短版本case obj:ClassA =>
return Json.toJson(obj)
case obj:ClassB =>
return Json.toJson(obj)
case obj:ClassC =>
return Json.toJson(obj)
// ... repeat 20 times for all the classes where I know I have a Writes
我尝试像unapply
那样接受一个隐含的但我无法接受没有语法错误的情况。
答案 0 :(得分:2)
您有两种选择:
Writes[ClassA]
,Writes[ClassB]
等您可能需要定义另一个部分功能并receive
调用该功能,因为您没有签名
Writes
实例转换为Json // companion object of ClassA
object ClassA {
val jsonWrites: Writes[ClassA]
}
由于在案例匹配范围内你知道它是ClassA,你可以直接使用Writes [ClassA]实例,所有内容都会进行类型检查。
case obj: ClassA =>
return ClassA.jsonWrites.writes(obj)
编辑:
第三个选项既不容易出错又灵活,它是定义一个函数列表:1。检查obj: Any
是T
的实例,如果是,则将其转换为Json。
这是我使用Scala工作表的最小代码段。见checkIsInstanceAndConvertToJson
:
import scala.reflect.ClassTag
case class Json(str: String)
trait Writes[A] {
def writes(obj: A): Json
}
// Generate a function that
// 1. Checks whether an object (Any) is an instance of `T`
// 2. Convert it to Json if it is
// The implementation of checking function. All unsafety is encapsulated
def checkIsInstanceAndConvertToJson[T: Writes](implicit t: ClassTag[T]): Any => Option[Json] = (obj: Any) => {
if (t.runtimeClass.isInstance(obj)) {
Some(implicitly[Writes[T]].writes(obj.asInstanceOf[T]))
}
else None
}
// ==========
// USAGE
// ==========
object Foo {
implicit val jsonWrites = new Writes[Foo] {
override def writes(obj: Foo) = Json("Foo")
}
}
class Foo
object Bar {
implicit val jsonWrites: Writes[Bar] = new Writes[Bar] {
override def writes(obj: Bar) = Json("Bar")
}
}
class Bar
// Defining a list of functions that checks whether
// an object is of an instance, and if so, converts it to Json
val checkFuncs = Vector[Any => Option[Json]](
checkIsInstanceAndConvertToJson[Bar],
checkIsInstanceAndConvertToJson[Foo]
)
val t: Any = new Bar
val iter = checkFuncs.iterator
var json: Option[Json] = None
while (json.isEmpty && iter.hasNext) {
val func = iter.next()
json = func(t)
}
println(json)
上述代码段打印Some(Json(Bar))