如何在Scala中操作JSON AST

Edu*_*rdo 9 scala lift-json json4s

我正在试验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)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我不喜欢它有很多原因:

  1. 必须明确地将结果parse(json)转换为JObject
  2. upsertField函数的结果是a JValue,如果我想进一步操作对象,我将不得不重新制作
  3. upsertField功能只是感觉很unelegant
  4. 它不适用于不在层次结构顶层的字段

有没有更好的方法来转换AST?

编辑:作为问题的解决方法,我已设法将我的JSON转换为Scala常规类,并使用镜头操作它们(在Scala常规类上使用镜头)

Ste*_*ger 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
  //    }
  //  }

}
Run Code Online (Sandbox Code Playgroud)