如何在 Scala 中操作 JSON AST [英] How to Manipulate JSON AST in Scala

查看:53
本文介绍了如何在 Scala 中操作 JSON AST的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试验 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:

  1. 必须将 parse(json) 的结果显式转换为 JObject
  2. upsertField 函数的结果是一个 JValue,如果我想进一步操作对象,我将不得不重新转换
  3. upsertField 函数感觉很不优雅
  4. 它不适用于不在层次结构顶层的字段
  1. Having to explicitly cast the results of parse(json) to JObject
  2. The result of the upsertField function is a JValue, which I will have to recast if I want to manipulate the object further
  3. The upsertField function just feels very unelegant
  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆