关于数组元素的PlayJson更新不起作用

时间:2018-04-10 15:28:59

标签: arrays json scala playframework play-json

我有一个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)) 我不明白为什么。 有人可以帮助我更新确切的元素。

1 个答案:

答案 0 :(得分:1)

您的地图未被调用,因为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

基本上:

  1. 读取(使用可选转换)由根对象
  2. 的路径标识的值
  3. 创建一个只包含那些路径和值的对象
  4. 将JsObject.deepMerge应用于根对象和值保持的
  5. 2)中使用的方法JsPath.createObj只能处理由键指定的路径,而不能处理索引。所以似乎不可能在play-json中修改嵌套数组的元素,至少开箱即用。

    同时在土地上: https://scastie.scala-lang.org/wRLs7O72ScyOmcMyiTU5uw