2014-02-13 7 views
3

Я бы ожидал, что json \\ "something" всегда будет возвращать тот же тип объекта (или, по крайней мере, что-то, что всегда изоморфно) для того же запроса данных с той же схемой, однако, считают:Оператор lift-json XPath \ имеет другой тип возврата в зависимости от числа совпадений

val json1 = ("people" -> List(
    ("person" -> ("name" -> "Joe")), 
    ("person" -> ("name" -> "Marilyn")))) 

val json2 = ("people" -> List(
    ("person" -> ("name" -> "Joe")))) 

val json3 = ("people" -> List[(String, String)]()) 

println((json1 \\ "name")) // JObject(List(JField(name,JString(Joe)), JField(name,JString(Marilyn)))) 
println((json2 \\ "name")) // JString(Joe) 
println((json3 \\ "name")) // JObject(List()) 

// which causes the following construction to sometimes fail 
println((json1 \\ "name").children map { case JField(_, JString(name)) => name }) 
// List(Joe, Marilyn) 
println((json2 \\ "name").children map { case JField(_, JString(name)) => name }) 
// List() !!!!! 
println((json3 \\ "name").children map { case JField(_, JString(name)) => name }) 
// List() 

... так п = 0 и п> = 2 случая обрабатываются последовательно, но п = 1 особых случаях JValue.

Почему это происходит? Это по дизайну?

Сравнение с отображением над List

val people = List(Person(name = "Joe"), Person(name = "Mary")) 
people.map(_.name) # => returns a List 

val people = List(Person(name = "Joe")) 
people.map(_.name) # => returns a List 

val people = List() 
people.map(_.name) # => returns a List 

Сравните с XML в Scala

val xml1 = <people> <person><name>Joe</name></person> <person><name>Marylin</name></person> <person><name>Erik</name></person> </people> 
val xml2 = <people> <person><name>Erik</name></person> </people> 
val xml3 = <people> </people> 

Seq(xml1, xml2, xml3).map(_ \\ "name") foreach (x => println(s"${x.getClass}\t${x.length}\t$x")) 

// OUTPUT:  
// class scala.xml.NodeSeq$$anon$1 3 <name>Joe</name><name>Marylin</name><name>Erik</name> 
// class scala.xml.NodeSeq$$anon$1 1 <name>Erik</name> 
// class scala.xml.NodeSeq$$anon$1 0 

так почему не следует ожидать, что подъем JSon \\ оператора, чтобы иметь ту же семантику ?

Док на http://liftweb.net/api/26/api/#net.liftweb.json.package имеет:

XPath-выражение, как для запроса JSON полей по имени. Возвращает все соответствующие поля.

+0

обсуждение на: https://groups.google.com/d/msg/liftweb/sf9ch59wEnI/XlPRq5juo8MJ –

ответ

1

В Json4s \\ теперь всегда возвращает JArray см here.

val json1 = 
    parse(""" 
    |{ 
    | "people": [{ 
    | "name": "Joe" 
    | }, { 
    | "name": "Marilyn" 
    | }] 
    |} 
    """.stripMargin) 

val json2 = 
    parse(""" 
    |{ 
    | "people": [{ 
    | "name": "Joe" 
    | }] 
    |} 
    """.stripMargin) 


println(json1 \\ "name") 
// JArray(List(JString(Joe), JString(Marilyn))) 

println(json2 \\ "name") 
// JArray(List(JString(Joe))) 
+0

Это хорошо, я думаю, что они могли бы быть фиксируя его в лифт 3.x тоже :) –

+0

В последней версии 3.5.0 я получаю JString (Joe) и JObject (List ((имя, JString (Joe)), (имя, JString (Marilyn)))) – Pascalius