我正在试验json4s库(基于lift-json)。我想做的一件事就是将JSON字符串解析为AST,然后对其进行操作。
例如,我想要一个字段(如果字段不存在则将字段插入AST,或者如果它存在则更新其值)。
我无法在文档中找到如何执行此操作。尝试了可用的方法,我提出了以下哪些方法有效,但感觉很笨拙。
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._
object TestJson {
implicit val formats = DefaultFormats
def main(args: Array[String]): Unit = {
val json = """{"foo":1, "bar":{"foo":2}}"""
val ast = parse(json).asInstanceOf[JObject]
println( upsertField(ast, ("foo" -> "3")) )
println( upsertField(ast, ("foobar" -> "3")) )
}
def upsertField(src:JObject, fld:JField): JValue = {
if(src \ fld._1 == JNothing){
src ~ fld
}
else{
src.replace(List(fld._1), fld._2)
}
}
}
我不喜欢它有很多原因:
parse(json)
的结果投射到JObject
upsertField
函数的结果是JValue
,如果我想进一步操纵对象,我将不得不重新制作upsertField
功能感觉非常不优雅有没有更好的方法来转换AST?
编辑:作为问题的解决方法,我设法将我的JSON转换为Scala常规类,并使用镜头操作它们(Using Lenses on Scala Regular Classes)答案 0 :(得分:12)
有一个合并功能可以创建或覆盖一个字段。您还可以更新不在树根级别的字段。
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._
object mergeJson extends App {
val json =
"""
|{
| "foo":1,
| "bar": {
| "foo": 2
| }
|}
|""".stripMargin
val ast = parse(json)
val updated = ast merge (("foo", 3) ~ ("bar", ("fnord", 5)))
println(pretty(updated))
// {
// "foo" : 3,
// "bar" : {
// "foo" : 2,
// "fnord" : 5
// }
// }
}
答案 1 :(得分:1)
我还要提供SON of JSON版本:
import nl.typeset.sonofjson._
val json = parse("""{ "foo" : 1, "bar" : { "foo" : 2 } }""")
// or, perhaps a little easier
val json = obj(foo = 1, bar = obj(foo = 2))
json.foo = "3"
json.foobar = "3"
答案 2 :(得分:0)
当我使用lift json实现一些非常具体的json diff时,我使用了很多递归函数来到我需要修改值的jpath,并且在递归“折叠”时构造了修改过的json。毕竟LiftJson是不可变的。你提到镜头是另一种方法,它本身就很有趣。但我目前最喜欢的是play-json库,当你需要进行json-to-json转换时,它就像魅力一样工作:
val gizmo2gremlin = (
(__ \ 'name).json.put(JsString("gremlin")) and
(__ \ 'description).json.pickBranch(
(__ \ 'size).json.update( of[JsNumber].map{ case JsNumber(size) => JsNumber(size * 3) } ) and
(__ \ 'features).json.put( Json.arr("skinny", "ugly", "evil") ) and
(__ \ 'danger).json.put(JsString("always"))
reduce
) and
(__ \ 'hates).json.copyFrom( (__ \ 'loves).json.pick )
) reduce
美味功能:所有变换器都是可以混合在一起的组合器,验证,无形支持,带隐式覆盖的案例类自动编组,独立库。