我正在选择一个好的Scala JSON库,大家一致认为lift-json是目前的最佳选择。
在使用它(版本2.5.1)一段时间后,我已经能够相当容易地完成我需要的大多数事情,除了一件事:修改现有的JValue。
假设我有以下JValue实例
val john = ("id" -> 1) ~
("name" -> "Foo") ~
("nested" ->
("id" -> 2) ~
("name" -> "Bar"))我想将父元素的名称从Foo更改为foo。我认为transform方法是可行的:
john transform {
case JField("name", _) => JField("name", "foo")
})但是这会将父元素和嵌套元素的name字段都更改为foo --回想起来,这并不奇怪。
我已经查看了文档和代码,但找不到一种方法来选择一个键为name的特定字段。我错过了什么吗?
另一个解决方案(这个解决方案也有效)似乎是合并两个JValue对象,但它似乎有点冗长:
john merge JObject(JField("name", "foo") :: Nil)有没有一种内置的、更具可读性的方法来达到同样的效果?我也许可以编写一个从JField到JObject的隐式转换,但lift-json还没有这样的机制,这似乎很奇怪。如果我必须打赌,那就是我没有找到它,而不是它不存在。
编辑:我现在觉得有点傻
john transform {
case JField("name", "Foo") => JField("name", "foo")
})这不是世界上最理想的解决方案,但它的可读性和简洁性都很好。
发布于 2013-07-19 03:09:35
这很难看,因为它使用了一个可变变量,还使用了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")
}
}
}我找不到一种更简洁的方法来告诉它要么只遍历一层深度,要么知道检查的每个节点的深度,所以我只会在第一层深度上进行切换。
发布于 2014-04-14 04:20:04
像这样使用JValue的replace方法:
john.replace(List("name"), "foo")
这个“替换”方法的实现是一场灾难,名称“替换”意味着(对我来说)一个不真实的状态修改,但它确实做到了。
JObject(List((id,JInt(1)), (name,JString(foo)), (nested,JObject(List((id,JInt(2)), (name,JString(Bar)))))))
https://stackoverflow.com/questions/17717419
复制相似问题