【问题标题】:Play Framework: How to replace all the occurrence of a value in a JSON treePlay Framework:如何替换 JSON 树中所有出现的值
【发布时间】:2014-02-15 12:48:47
【问题描述】:

鉴于以下 JSON...

{ "id":"1234",
  "name" -> "joe",
  "tokens: [{
     "id":"1234",
     "id":"2345"
   }]
}

...我需要将所有ids 的值替换为xxxx,如下所示:

{ "id":"xxxx",
  "name" -> "joe",
  "tokens: [{
     "id":"xxxx",
     "id":"xxxx"
   }]
}

让我们开始创建 JSON 树:

val json = Json.obj(
  "id" -> "1234",
  "name" -> "joe",
  "tokens" -> Json.arr(
     Json.obj("id" -> "1234"),
     Json.obj("id" -> "2345")
  )
)

json: play.api.libs.json.JsObject = {"id":"1234","name":"joe","tokens":[{"id":"1234"},{"id":"2345"}]}

那么,获取所有ids 就很简单了:

 json \\ "id"

 res64: Seq[play.api.libs.json.JsValue] = List("1234", "1234", "2345")

现在,如何将所有ids 的值替换为xxxx

【问题讨论】:

    标签: json scala playframework


    【解决方案1】:

    使用标准 Play JSON 库似乎没有一个很好的方法来做到这一点,尽管我很高兴在这方面被证明是错误的。但是,您可以使用 play-json-zipper 扩展轻松做到这一点:

    import play.api.libs.json._
    import play.api.libs.json.extensions._
    
    val json = Json.obj(
      "id" -> "1234",
      "name" -> "joe",
      "tokens" -> Json.arr(
        Json.obj("id" -> "1234"),
        Json.obj("id" -> "2345")
      )
    )
    
    // Using `updateAll` we pattern match on a path (ignoring
    // the existing value, as long as it's a string) and replace it
    val transformed = json.updateAll {
      case (__ \ "id", JsString(_)) => JsString("xxxx")
    }
    
    // play.api.libs.json.JsValue = {"id":"xxxx","name":"joe","tokens":[{"id":"xxxx"},{"id":"xxxx"}]}
    

    要使其成为可重复使用的功能:

    def replaceValue(json: JsValue, key: String, replacement: String) = json.updateAll {
      case (__ \ path, JsString(_)) if path == key => JsString(replacement)
    }
    

    json-zipper 扩展仍然是“实验性的”,但如果您想将它们添加到您的项目中,请将以下内容添加到您的 project/Build.scala appDependencies:

    "play-json-zipper" %% "play-json-zipper" % "1.0"
    

    以及以下解析器:

    "Mandubian repository releases" at "https://github.com/mandubian/mandubian-mvn/raw/master/releases/"
    

    【讨论】:

    • Tx,已经尝试过了...但是我需要将密钥作为参数传递,这种情况下它不起作用:def toXXXX(json: JsValue, key: String) = json.update { case ((_ \ key), value) => JsString(value) }
    • @j3d:你能定义“不起作用”吗?如果键和替换值都是参数,我添加了一个示例。您在评论中发布的代码看起来错误(您需要使用 updateAll 并且您正在将现有值与所需的替换匹配。)
    • 喘气,你的工作完美。问题是真实的例子更复杂。我刚刚发布了一个新问题 [stackoverflow.com/questions/21801071/… - 如果还不无聊,您可以快速浏览一下;-)
    【解决方案2】:

    这可能不是最有效的方法,但您可以尝试将 JSON 转换为对象并使用新字段复制它,然后将其转换回 json。不幸的是,目前我没有检查代码的环境,但它应该是这样的:

    case class MyId(id: String)
    case class MyObject(id: String, name: String, tokens: List[MyId])
    
    implicit val idFormat = Json.format[MyId]
    implicit val objectFormat = Json.format[MyObject]
    
    val json = Json.parse(jsonString)
    val jsResult = Json.fromJson[MyObject](json)
    
    val obj = jsResult match {
          case JsSuccess(s, _) => s
          case _ => throw new IllegalStateException("Unexpected")
        }
    
    val newObj = obj.copy(id = "xxxx")
    val result = Json.toJson(newObj)
    

    【讨论】:

      猜你喜欢
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多