Как обновить вложенный json с помощью scala play Framework?

#scala #play-json

#scala #воспроизведение-json

Вопрос:

Я пытаюсь обновить значение json, присутствующее в json, используя Scala play framework.Вместо обновления значения оно добавляет значение.

 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:

Цитирование из update документации по методу:

( __ ‘key).json.update (reads) является самым сложным Reads [JSObject], но самым мощным:

  • копирует все значение JsValue => A

  • применяет переданные чтения [A] к JsValue => B

  • deep объединяет оба JsValues (A B), поэтому B перезаписывает идентичные ветви. Пожалуйста, обратите внимание, что если вы обрезали ветку в 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.