0

我正在选择一个好的 Scala JSON 库,并且共识似乎lift-json是目前最好的选择。

在使用它(版本 2.5.1)一段时间后,我已经能够相当轻松地完成大部分我需要的事情,除了一个:修改现有的JValue.

假设我有以下实例JValue

val john = ("id"   -> 1) ~
           ("name" -> "Foo") ~
           ("nested" ->
             ("id" -> 2) ~
             ("name" -> "Bar"))

我想将父元素的名称从更改Foofoo. 我认为该transform方法是要走的路:

john transform {
    case JField("name", _) => JField("name", "foo")
})

但这会将父元素和嵌套元素的name字段都更改为foo- 回想起来,这真的不应该是一个惊喜。

我查看了文档和代码,但找不到一种方法来选择具有 .key 键的特定字段name。我错过了什么?

另一种解决方案(这个可行)似乎是合并两个JValue对象,但似乎有点冗长:

john merge JObject(JField("name", "foo") :: Nil)

是否有一种内置的、更易读的方法来实现相同的结果?我可能可以编写一个从JFieldto的隐式转换,但还没有这样的机制JObject似乎很奇怪。lift-json如果我必须打赌,那就是我没有找到它,而不是它不存在。

编辑:我现在觉得有点傻

john transform {
    case JField("name", "Foo") => JField("name", "foo")
})

不是世界上最佳的解决方案,但完全可读和简洁。

4

2 回答 2

0

像这样使用replaceJValue 的方法:

john.replace(List("name"), "foo")

这种'replace'方法的实现是一场灾难,并且名称replace(对我来说)暗示了一个不正确的状态修改,但它确实做到了

JObject(List((id,JInt(1)), (name,JString(foo)), (nested,JObject(List((id,JInt(2)), (name,JString(Bar)))))))

于 2014-04-13T20:20:03.860 回答
0

这很难看,因为它使用了一个可变变量,并且它还使用了 json4s(它在后台使用 lift-json),但它可以工作:

import org.json4s.JsonAST._
import org.json4s.native.JsonMethods._
import org.json4s.JsonDSL._

object JsonTesting {
  def main(args: Array[String]) {
    val john = ("id"   -> 1) ~
           ("name" -> "Foo") ~
           ("nested" ->
             ("id" -> 2) ~
             ("name" -> "Bar"))

    var changed = false
    val john2 = john transformField {
      case JField("name", _) if !changed => 
        changed = true
        JField("name", "foo")
    }
  }
}

我找不到更简洁的方法来告诉它要么只遍历一个深度级别,要么知道每个检查节点的深度,所以我只会在第一级深度上进行切换。

于 2013-07-18T19:09:35.370 回答