2014-10-07 100 views
2
import play.api.libs.json._ 

val json: JsValue = Json.parse(""" 
    { 
    "name" : "Independence", 
    "foundingFathers" : [ { 
     "name" : { 
     "first": "John", 
     "last": "Adams" 
     }, 
     "country" : "United States" 
    }, { 
     "name" : { 
     "first": "Artur", 
     "last": "Mas" 
     }, 
     "country" : "Catalonia" 
    } ] 
    } 
""") 

val lastNames = json \ "foundingFathers \ "name" \ "last" 
// this does not work. it fails with: JsUndefined('last' is undefined on object: JsUndefined('name' is undefined on object: [{"name":{"first":"John","last":"Adams"},"country":"United States"},{"name":{"first":"Artur","last":"Mas"},"country":"Catalonia"}])) 

// this does work, but there is too much boilerplate 
val lastNames = (json \ "foundingFathers").as[List[JsObject]].map(_ \ "name" \ "last") 

如何在沒有該樣板的情況下實現結果? (在這種情況下,我想用JsValues,我不想用一個讀者JsValue轉換成模型)JsPath在斯卡拉播放Json

+2

一個行太畝ch boilerplate ?? – 2014-10-07 13:11:39

+1

您不認爲第一種方法(可以在XML XPath中工作)比第二種方法更簡單?這只是一個簡單的例子,還有更復雜的路徑查詢... – 2014-10-07 13:16:34

回答

3

可以使用隱式類包裹它使用這一功能

的代碼
implicit class JsValueWrapper(val j: JsValue) extends AnyVal { 
    def \|(fieldName: String) = j match { 
    case JsArray(value) => JsArray(value.map(_ \ fieldName)) 
    case _ => j \ fieldName 
    } 
} 

scala> json \| "foundingFathers" \| "name" \| "first" 
res19: play.api.libs.json.JsValue = ["John","Artur"] 
2

未愈,不能確定它是否回答您的問題

val lastNames = json \ "foundingFathers" \\ "name" map (_ \ "last") 

lastNames:序號[play.api.libs.json.JsValue] = ListBuffer(「亞當斯」,「馬斯」)

+1

\\是一個遞歸路徑,這不是我想要的;例如,如果'country'字段是一個名爲'name'的子結構,那麼遞歸路徑也會找到那些JSON節點,而我只想要foundingFathers的直接子節點。 – 2014-10-07 13:14:04