2017-08-05 19 views
2

Play Framework提供了一種通過隱式Writes將對象轉換爲JSON的方法。檢查是否存在隱式匹配情況

def toJson[T](o: T)(implicit tjs: Writes[T]): JsValue 

我有一個部分函數正在處理消息,其中一些可能可串行化爲JSON(如果存在一個Writes)。我如何編寫一個與隱式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

Implicits是一個編譯時的功能,所以即使在運行時行爲的對象匹配他們沒有多大意義。你所需要做的就是要求該方法爲「T」提供一個隱含的證據。如果它沒有找到,編譯器會在編譯時告訴你。 –

+0

問題是我匹配的對象是Any,而我有20多個隱式Writes。我想爲「一個隱式Writes存在的類之一的對象」寫一個案例。這應該是在編譯時可能的,對吧?這只是枚舉自己的20多個類型的較短版本 – takteek

+1

[Test if implicit conversion is available](https://stackoverflow.com/questions/5717868/test-if-implicit-conversion-is-available) –

回答

2

你有兩個選擇:

1.要求所有Writes[ClassA]Writes[ClassB]等在功能

您可能需要定義另一部分功能,並有receive通話,既然你沒有簽名

2.使用Writes實例都可以直接轉換成JSON

// companion object of ClassA 
object ClassA { 
    val jsonWrites: Writes[ClassA] 
} 

並且由於在case匹配範圍內您知道它是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))