如何在 Scala 中操作 JSON AST [英] How to Manipulate JSON AST in Scala
问题描述
我正在试验 json4s 库(基于lift-json).我想做的一件事是将 JSON 字符串解析为 AST,然后对其进行操作.
I am experimenting with the json4s library (based on lift-json). One of the things I would like to do is to parse a JSON string into an AST, and then manipulate it.
例如,我想插入一个字段(如果该字段不存在,则将其插入到 AST 中,如果存在则更新其值).
For example, I would like to upsert a field (insert the field into the AST if it does not exist, or update its value if it does).
我无法在文档中找到如何执行此操作.尝试了可用的方法,我想出了以下方法,虽然有效,但感觉很笨拙.
I have not been able to find how to do it in the documentation. Experimenting with the available methods, I have come up with the following, which works, but feels clumsy.
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)
}
}
}
我不喜欢它的原因有很多:
I dislike it for many reasons:
- 必须将
parse(json)
的结果显式转换为JObject
upsertField
函数的结果是一个JValue
,如果我想进一步操作对象,我将不得不重新转换upsertField
函数感觉很不优雅- 它不适用于不在层次结构顶层的字段
- Having to explicitly cast the results of
parse(json)
toJObject
- The result of the
upsertField
function is aJValue
, which I will have to recast if I want to manipulate the object further - The
upsertField
function just feels very unelegant - It does not work for fields that are not at the top level of the hierarchy
有没有更好的方法来转换 AST?
Is there a better way to transform the AST?
作为该问题的解决方法,我设法将我的 JSON 转换为 Scala 常规类,并使用镜头操作它们(在 Scala 常规类上使用镜头)
as a workaround to the problem, I have managed to convert my JSON to Scala regular classes, and manipulate them with lenses (Using Lenses on Scala Regular Classes)
推荐答案
有创建或覆盖字段的合并函数.您还可以更新不在树根级别的字段.
There is the merge function which creates or overrides a field. You can also update fields that are not at the root level of the tree.
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
// }
// }
}
这篇关于如何在 Scala 中操作 JSON AST的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!