如何使用Scala Play框架更新嵌套的json?

时间:2020-10-09 13:05:29

标签: scala play-json

我正在尝试使用Scala play框架更新json中存在的json值,而不是更新值,而是附加值。

val newJsonString = """{"P123": 25}"""
val jsonStringAsJsValue = Json.parse("""{"counter_holders": {"Peter": 25}}""")
//jsonStringAsJsValue: play.api.libs.json.JsValue = {"counter_holders":{"Peter":25}}

val jsonTransformer = (__ \"counter_holders" ).json.update(__.read[JsValue].map{o => Json.parse(newJsonString)})

jsonStringAsJsValue.transform(jsonTransformer).get.as[JsValue]
//Now getting this jsvalue
//play.api.libs.json.JsValue = {"counter_holders":{"Peter":25,"P123":25}}
//But need  this jsvalue
//play.api.libs.json.JsValue = {"counter_holders":{"P123":25}}

任何对此的帮助都会非常好。

1 个答案:

答案 0 :(得分:1)

update方法文档中引用:

({__ \'key).json.update(reads)是最复杂的读取[JsObject] 但最强大的:

  • 复制整个JsValue => A

  • 在JsValue => B上应用传递的Reads [A]

  • 深度合并两个JsValues(A ++ B),因此B覆盖A相同的分支请注意,如果在B中修剪了一个分支,则仍然 在A中,您将在结果示例中看到它:

    {{{ val js = Json.obj("key1" -> "value1", "key2" -> "value2")
    js.validate(__.json.update((__ \ 'key3).json.put(JsString("value3"))))
    => JsSuccess({"key1":"value1","key2":"value2","key3":"value3"},) }}}
    

因此,您看到的行为是预期的。如果要采用这种方法,即使用路径进行更新,则可以使用方法prune。例如,您可以这样做:

val newJsonString = """{"P123": 25}"""
val jsonStringAsJsValue = Json.parse("""{"counter_holders": {"Peter": 25}}""")
//jsonStringAsJsValue: play.api.libs.json.JsValue = {"counter_holders":{"Peter":25}}

val jsonTransformer = (__ \"counter_holders" ).json
  .update(__.read[JsValue].map{o => Json.parse(newJsonString)})

val jsonTransformerDelete = (__ \"counter_holders" \ "Peter" ).json.prune

jsonStringAsJsValue.transform(jsonTransformer).flatMap(_.transform(jsonTransformerDelete)) match {
  case JsSuccess(value, _) =>
    println(value)
  case JsError(errors) =>
    println(errors)
}

这将产生想要的行为。您可以在scastie中找到它。