У меня есть json
val js = Json.obj("val" -> Json.arr(Json.obj("a" -> Json.arr(1))))
И я хочу обновить его
Json.obj("val" -> Json.arr(Json.obj("a" -> Json.arr(1))))
.transform((__ \\ "val") (0).json.update(__.read[JsArray].map { jsVal => println(jsVal); jsVal }))
В моем сообщении об обновлении ничего не печатается. и даже в отладку не заходите.
Но методы pick находят этот элемент.
js.transform((__ \\ "val")(0).json.pick)
вернуть JsSuccess({"a":[1]},//val(0))
Я не могу понять почему.
Может ли кто-нибудь помочь мне, как обновить точный элемент.



Ваша карта не вызывается, потому что read [JsArray] фактически возвращает JsError:
val js = Json.obj("val" -> Json.arr(Json.obj("a" -> Json.arr(1))))
val result1 = js.transform((__ \\ "val") (0).json.update(Reads.of[JsArray]))
println(result1)
// JsError(List((//val(0),List(JsonValidationError(List(error.expected.jsarray),WrappedArray())))))
Вы можете распечатать вызывающее его значение следующим образом:
val result2 = js.transform((__ \\ "val")(0).json.update(
Reads(v => { println(v); v.validate[JsArray] })
))
println(result2)
// {"a":[1]} - same value as in pick!
// JsError(List((//val(0),List(JsonValidationError(List(error.expected.jsarray),WrappedArray()))))
Теперь мы знаем, что это объект, так что давайте попробуем прикоснуться к нему.
val result3 = js.transform((__ \\ "val")(0).json.update(Reads.of[JsObject]))
println(result3)
// java.lang.RuntimeException: expected KeyPathNode
Проверим реализацию обновления: https://github.com/playframework/play-json/blob/2.6.9/play-json/shared/src/main/scala/play/api/libs/json/JsConstraints.scala#L85-L94
Это в основном:
Метод JsPath.createObj, используемый в 2), может обрабатывать пути, указанные только ключами, но не индексами. Кажется, что невозможно изменить элементы вложенных массивов в play-json, по крайней мере, из коробки.
Между тем в цирке: https://scastie.scala-lang.org/wRLs7O72ScyOmcMyiTU5uw