2014-10-07 2 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") 

어떻게 그런 상용구없이 결과를 얻을 수 있습니까? 이스칼라로 배열하기위한 JsPath 재생 Json

+2

한 줄이 너무 무 ch 상용구 ?? –

+1

XML XPath에서 작동하는 첫 번째 접근 방식이 두 번째 방식보다 훨씬 간단하다고 생각하지 않습니까? 그리고 이것은 단지 사소한 예입니다. 더 복잡한 경로 질의가 있습니다 ... –

답변

3

= ListBuffer ("아담스", "마스")는

코드의
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

작은 개선 (나는 JsValues를 사용하려면이 경우에, 나는 모델에 JsValue을 변환하는 리더를 사용하지 않음), 확인 여부는 귀하의 질문

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

라스트 네임 응답 : 서열 [play.api.libs.json.JsValue]이 기능을 사용하여 포장을위한 암시 클래스를 사용할 수 있습니다

+1

\\는 재귀 경로입니다. 예를 들어'country' 필드가'name'이라는 이름의 자식 구조를 가진 경우 재귀 적 경로는 json 노드를 찾을 수 있습니다. –

관련 문제