4

Are my eyes deceiving me or can I not update a nested node with a JsPath containing an array element in between? (e.g. /a/b(0)/c)

val pnJson = Json.parse("""{"a": {"b": [ {"c": { "d": 1 } } ] } } """)                                     
val pnJsPath = (__ \ "a" \ "b")(0) \ "c"                                                                   
val pnTrans = pnJsPath.json.update ( __.read[JsObject].map{ _ ++ Json.obj( "e" -> 2 )} )

pnJson.transform(pnTrans)

//result: java.lang.RuntimeException: expected KeyPathNode

If I cant use __.json.update, How can I accomplish this? Trying to accomplish this with immutablity.

4

2 回答 2

3

简短的回答是你不能用JsPath. 该票提到使用JsZipper库作为操作 JSON 的更好方法。如果您选择使用它,您可以执行以下操作:

scala> import play.api.libs.json.extensions._
import play.api.libs.json.extensions._

scala> import play.api.libs.json.monad.syntax._
import play.api.libs.json.monad.syntax._

scala> val pnJson = Json.parse("""{"a": {"b": [ {"c": { "d": 1 } } ] } } """) 
pnJson: play.api.libs.json.JsValue = {"a":{"b":[{"c":{"d":1}}]}}

scala> val pnJsPath = (__ \ "a" \ "b")(0) \ "c" 
pnJsPath: play.api.libs.json.JsPath = /a/b(0)/c

scala> pnJson.update(pnJsPath, _.set(__ \ "e" -> JsNumber(2)))
res0: play.api.libs.json.JsValue = {"a":{"b":[{"c":{"d":1,"e":2}}]}}

否则,最好的办法是将任务分成两部分,第一部分解析数组,第二部分将其转换为具有修改内容的新数组。

于 2014-10-10T05:35:29.580 回答
1

只是为了线程的完整性,后来的版本似乎允许操作很好,例如在途中修剪数组。下面的一个例子:

import play.api.libs.json._
val j = Json.parse("""{"name":"Test","towns":[{"twn":{"id":1,"status":["A","B"]}}, {"twn":{"id":2,"status":["B"]}}, {"twn":{"id":3,"status":["B","C"]}}]}""")
val t = (__ \ "towns").json.update(
          Reads.list(
            (__ \ "twn" \ "id").json.prune
              ).map(JsArray(_)))
j.transform(t)

如果其中一个数组对象不包含“id”,则会出现一些问题,但在大多数情况下,这将完成这项工作。

于 2019-09-23T13:30:27.317 回答