【问题标题】:Play framework JSON transformers, how to work with recursive paths (jsPath)?播放框架 JSON 转换器,如何使用递归路径(jsPath)?
【发布时间】:2018-10-05 21:58:55
【问题描述】:

假设我有一个这样的 JSON:

{
  "name" : "Watership Down",
  "location" : {
    "lat" : 51.235685,
    "long" : -1.309197
  },
  "residents" : [ {
    "name" : "Fiver",
    "age" : 4,
    "role" : null
  }, {
    "name" : "Bigwig",
    "age" : 6,
    "role" : "Owsla"
  } ]
}

如果我这样做了

val transformer1 = (__ \ 'name).json.update(of[JsValue].map(a => JsString("x")))

name 字段更改为"x" 可以正常工作。

但如果我想递归地将所有名称更改为"x",我想我可以只使用递归jsPath,如下所示:

val transformerRecursive = (__ \\ 'name).json.update(of[JsValue].map(a => JsString("x")))

但是当我尝试时,我得到了这个错误:

scala> jsobject.transform(transformerRecursive) res1: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsError(List((//name,List(ValidationError(List(error.path.result.multiple),WrappedArray()) )))))

我应该如何在 playframework 中使用带有 JSON Transformer 的递归路径?

【问题讨论】:

  • 我认为错误报告'name 属性有多个匹配项。您可能需要遍历它们并单独更新它们

标签: scala playframework


【解决方案1】:

正如@irundaia 所说,您需要遍历数组并更新每个值(为此使用Reads.list):

val t = (__ \ "residents").json.update(
  Reads.list(
    (__ \ "name").json.update(
      Reads.pure(JsString("x"))
    )
  ).map(JsArray)
)

scala> res1: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"name":"Watership Down","location":{"lat":51.235685,"long":-1.309197},"residents":[{"name":"x","age":4,"role":null},{"name":"x","age":6,"role":"Owsla"}]},/residents)

【讨论】:

    【解决方案2】:

    感谢@andrey.ladniy,我设法解决了我想清空嵌套 JsArray 的问题。以下是如何做到这一点的示例,仅供任何可能找到任何帮助的人使用:

    import play.api.libs.json._
    
    case class D(yay: String, nay: String)
    case class C(ds: Seq[D], baz: Boolean)
    case class B(cs: Seq[C], bar: Int)
    case class A(b: B, foo: String)
    
    implicit val formatD: OFormat[D] = Json.format
    implicit val formatC: OFormat[C] = Json.format
    implicit val formatB: OFormat[B] = Json.format
    implicit val formatA: OFormat[A] = Json.format
    
    val foo = A(
      B(Seq(C(Seq(D("foo", "bar")), true), C(Seq(D("oof", "rab")), false)), 42),
      "test"
    )
    
    val dsIgnoringReads =
      (__ \ "b" \ "cs").json.update(Reads.seq((__ \ "ds").json.update(Reads.pure(JsArray()))).map(JsArray))
    
    dsIgnoringReads.reads(Json.toJson(foo)).get
    

    这会产生

    res0: play.api.libs.json.JsObject = 
      {"b":{"cs":[{"ds":[],"baz":true},{"ds":[],"baz":false}],"bar":42},"foo":"test"}
    

    【讨论】:

      猜你喜欢
      • 2018-05-03
      • 2020-11-17
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多