scala - lift-json XPath\\operator 根据 num 匹配有不同的返回类型

标签 scala xpath lift lift-json json4s

我希望 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-like expression to query JSON fields by name. Returns all matching fields.

最佳答案

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

关于scala - lift-json XPath\\operator 根据 num 匹配有不同的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21762259/

相关文章:

scala - 我们如何在 Lift 片段中获取当前页面的 URL?

.net - 如何使用XPath伪造不存在的XML节点?

php - 如何防止 DOMXPath 扩展 HTML 实体?

android - 问题 : "Extracting" JSON using lift-json in an Android (Scala) application

scala - MongoDB - 按引用排序或 'Foreign Key' (Liftweb, Scala)

json - 如何在 Scala/Lift 中构造和解析 JSON 字符串

scala - 为什么这个 `case` 是必须的?

arrays - 在 Scala 中初始化时如何强制数组的类型?

python - 如何使用 selenium 从内联 css 获取背景图像

scala - 仅将 @BeanProperty 用于 setter 生成