The lift-json XPath \\ statement has a different return type depending on the number of matches

I would expect it to json \\ "something"always return the same type of object (or at least something that is always isomorphic) for the same data request with the same schema, however, consider:

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()

... therefore, the operations n = 0 and n> = 2 are processed sequentially, but n = 1 special cases for JValue.

Why is this happening? Is it for design?

Comparison with display over 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

Compare with Scala XML

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   

why not expect the lift-json operator \\to have the same semantics?

The document at http://liftweb.net/api/26/api/#net.liftweb.json.package has:

XPath-like JSON . .

+3
1

Json4s \\ a JArray, . .

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)))
+1

All Articles