2015-08-29 19 views

回答

19

通常你知道編碼器總是會產生一個JSON對象(而不是任意的JSON值)。在類型系統中跟蹤這個事實使得可以使用這樣的編碼器的輸出來工作,而不用跳過通常是必需的環。

例如,假設我們有一個簡單的類:

class Foo(val name: String, val age: Long) 

我們寫一個Writes情況是這樣的:

import play.api.libs.functional.syntax._ 
import play.api.libs.json._ 

implicit val fooWrites: Writes[Foo] = (
    (__ \ 'name).write[String] and (__ \ 'age).write[Long] 
)(foo => (foo.name, foo.age)) 

現在我們可以寫:

scala> val json = fooWrites.writes(new Foo("McBar", 101)) 
json: play.api.libs.json.JsValue = {"name":"McBar","age":101} 

現在假設我們想要得到一個字段名稱列表,無論出於何種原因。我們必須寫這樣的事:

scala> json.as[JsObject].keys 
res0: scala.collection.Set[String] = Set(name, age) 

取而代之的是:

scala> json.keys 
<console>:17: error: value keys is not a member of play.api.libs.json.JsValue 
       json.keys 
       ^

但當然我們知道json將永遠是一個JsObject。問題是編譯器沒有。 OWrites解決了這個問題。

implicit val fooWrites: OWrites[Foo] = (
    (__ \ 'name).write[String] and (__ \ 'age).write[Long] 
)(foo => (foo.name, foo.age)) 

然後:

scala> val json = fooWrites.writes(new Foo("McBar", 101)) 
json: play.api.libs.json.JsObject = {"name":"McBar","age":101} 

scala> json.keys 
res1: scala.collection.Set[String] = Set(name, age) 

writesOWrites輸出靜態類型爲JsObject,所以我們可以使用.keys沒有不安全as[JsObject]演員。

(作爲一個方面說明,我製作方法的返回類型的子類更具體的not personally a fan,我已經採取了a slightly different approachcirce解決這個問題。)

+0

所以,你說的是,如果我知道某個東西是Json對象(而不是Json數組)比實現一個OWrites而不是一個Writes更好,對吧?關於「不是個人粉絲」中的鏈接,我無法在任何地方找到「更具體的返回類型」,所以我無法得到這個想法。你能解釋一下你連接的問題嗎?感謝OWrites的解釋:) – vicaba

+1

如果您的用例需要它,則更爲可取。我不知道'OWriter'是否給你比普通的'Writer'更多/不同的功能,除了你在編譯時知道它是一個JsObject。我認爲@Travis所說的「更具體的返回類型」是指'OWrites [T]擴展Writes [T]'其中'Writest [T]''def寫入(in:T):JsValue',而同樣的方法在'OWrites [T]'是'def writes(in:T):JsObject',其中'JsObject'是'JsValue'的子類。 – goral

+0

@goral是的,我在Writes和OWrites的例子中看到了這個想法,但是我不明白的是這裏發生了什麼:http:// stackoverflow。com/questions/31080332/why-is-upcasting-necessary-in-this-scala-code#comment50187425_31080332 – vicaba

相關問題