检查匹配大小写中是否存在隐式

时间:2017-08-05 05:45:48

标签: scala playframework

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那样接受一个隐含的但我无法接受没有语法错误的情况。

1 个答案:

答案 0 :(得分:2)

您有两种选择:

1。在您的函数中需要所有Writes[ClassA]Writes[ClassB]

您可能需要定义另一个部分功能并receive调用该功能,因为您没有签名

2。直接使用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: AnyT的实例,如果是,则将其转换为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))