【问题标题】:update json values with json4s for a json path使用 json4s 为 json 路径更新 json 值
【发布时间】:2016-09-07 19:50:33
【问题描述】:

我想更新我的 Json 中的 json 值。我尝试使用转换字段和替换方法,但每个方法都有一个问题阻止我继续。所以我正在寻求一些帮助。我必须创建一个采用 Map 参数列表的方法,该 Map 中的键对应于 Json 路径,值是要更新的值,例如:

def jsonFieldUpdater( SeaarchKey :  List(Map(key, VALUE ) )

所以在地图中我有一个 Json 路径 [\inner\age, 30 ] 作为 key ;我的方法读取它并更新该字段而不是所有年龄键。见下例

{"name":"luca", "id": "1q2w3e4r5t", "age": 26, "inner": { "age": 27 }, "url":"http://www.nosqlnocry.wordpress.com"}

我有点卡在这里,好像我使用 Use transformfield 方法它会更新所有以年龄为键的值,我不希望我想去一个特定的路径并对其进行转换。我的代码块是:

import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._
object Json4sTest {  
  def main(arg: Array[String]) {
    //val source = scala.io.Source.fromFile("file.txt")
    //val lines = try source.mkString finally source.close()
    var json = parse("""{"name":"luca", "id": "1q2w3e4r5t", "age": 26, "inner": { "age": 27 }, "url":"http://    www.nosqlnocry.wordpress.com"}""")
    println(pretty(json))
    //JObject(List(JField("foo", JObject(List(JField("bar", JInt(1))))))).replace("foo" :: "bar" :: Nil, JString("baz"))
    json = json.replace("inner" :: "age" :: Nil, 29)
    json = json transformField {
    case ("name", _) => ("NAME", JString("Tuca"))
    case ("age", JInt(age)) => ("age", JInt(age+1))
    //case ("checkIn", date) => ("checkIn", JString(df.print(now.plusDays(deltaIn))))
    }
    println(pretty(json))

  }
}

我遇到了替换值的替换方法。但它看起来像这样: json = json.replace("内在" :: "年龄" :: Nil, 29) 当我刚刚收到一个具有 Json 路径和必须更新的值的地图时,我无法思考如何符合这种格式。还有其他想法可以实现相同的目标吗?

我尝试了 n4to4 的解决方案,但是当我将 Map 列表分配给一个变量时,我得到了错误,例如:

val a = List(Map("inner/age" -> 35, "age" -> 27, "name" -> "foo"))
jsonFieldUpdater(json, a )
// error : type mismatch; found :    List[scala.collection.immutable.Map[String,Any]] required: List[Map[String,org.json4s.JValue]] (which expands to) List[Map[String,org.json4s.JsonAST.JValue]]

【问题讨论】:

标签: scala json4s


【解决方案1】:

不一定是ListMap 可能...?

import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._

object Json4sTest {
  def main(arg: Array[String]) {
    var json = parse("""{"name":"luca", "id": "1q2w3e4r5t", "age": 26, "inner": { "age": 27 }, "url":"http://    www.nosqlnocry.wordpress.com"}""")
    println(pretty(json))

    val a: List[Map[String, JValue]] = List(Map("inner/age" -> 35, "age" -> 27), Map("name" -> "foo"))
    val r = jsonFieldUpdater(json, a)
    println(pretty(r))

    val b = List(Updater("inner/age", 35), Updater("age", 27), Updater("name", "foo"))
    val s = jsonFieldUpdater2(json, b)
    println(pretty(s))
  }

  def jsonFieldUpdater(json: JValue, list: List[Map[String, JValue]]): JValue =
    list.foldLeft(json) { case (json, kvs) =>
      kvs.foldLeft(json) { case (json, (key, value)) =>
        json.replace(key.split("/").toList, value)
      }
    }

  case class Updater(key: String, value: JValue) {
    def path: List[String] = key.split("/").toList
  }

  def jsonFieldUpdater2(json: JValue, list: List[Updater]): JValue =
    list.foldLeft(json) { case (json, u) =>
      json.replace(u.path, u.value)
    }
}

【讨论】:

  • 我试过了,看起来不错,但我发现如果我确实使用一个变量来存储地图列表,例如: val a = List(Map("inner/age" -> 35, "age" -> 27, "name" -> "foo")) 然后调用 jsonFieldUpdater(json, a) // 给我一个错误:“type mismatch; found : List[scala.collection.immutable.Map[String ,Any]] 必需:List[Map[String,org.json4s.JValue]](扩展为)List[Map[String,org.json4s.JsonAST.JValue]]"
  • 您需要明确指定类型,或者您可能想要引入自定义类型(上面的Updater),这对我来说似乎更清楚。
  • 嗨。我已经成功地将您的解决方案用于路径值,但它在修补数组时失败了。例如。 { "id": "20", "elements": { "children": [ { "name": "John Doe", "address": "City street 2" }, { "navn": "Jane Doe", "address": "City street 3" } ] } } 我试过这样的事情: val a: List[Map[String, JValue]] = List(Map("elements/children[0]/address" -> "Farming way 2", "elements/children[1]/address" -> "Farming way 3")) val r = jsonFieldUpdater(json, a) 你有解决办法吗?
【解决方案2】:

您可以尝试以下代码来更新字段

import org.json4s.JValue
import org.json4s.JsonAST.JObject
import org.json4s.jackson.JsonMethods._

val msgJson = "{\"outer\":\"before\",\"inner\": { \"age\": 1 }}"
val msgJValue: JValue = parse(msgJson)
val mergeJValue = msgJValue merge JObject(
  List(
    ("outer", JString("after")),
    ("inner", JObject(List(("age", JInt(100)))))
  )
)
println(compact(render(mergeJValue)))//{"outer":"after","inner":{"age":100}}

【讨论】:

    【解决方案3】:

    怎么样

    json.replace(path.split("/").toList,myNewJvalue)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-02
      • 2018-12-19
      • 1970-01-01
      相关资源
      最近更新 更多