lift-json XPath \ 运算符具有不同的返回类型,具体取决于匹配数



我希望json \ "something"总是为具有相同模式的数据的相同查询返回相同类型的对象(或至少始终是同构的对象),但是,请考虑:

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

。因此,n = 0 和 n>= 2 个情况得到一致处理,但 n = 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

与 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   

那么,为什么不应该期望 lift-JSON \ 运算符具有相同的语义呢?

http://liftweb.net/api/26/api/#net.liftweb.json.package 的文档有:

类似 XPath 的表达式,用于按名称查询 JSON 字段。返回所有匹配的字段。

在 Json4s 中\现在总是返回一个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)))

相关内容

  • 没有找到相关文章

最新更新