通过将一个项添加到其中一个包含数字数组的分支来更新JsObject

时间:2015-04-15 14:40:10

标签: json scala playframework

我有JsObject的动态内容,例如:

{
    "foo": "bar",
    "viewedTaskIds": [1, 2, 3, 4]
}

viewedTaskIds是一个整数数组。

我想要做的是更新此JsObject并添加一个新号码(让我们说5)到viewTaskIds。我希望结果为JsObject

如何在Play Framework Scala应用程序(v2.3)中执行此操作?

编辑:如果分支viewedTaskIds不存在,则应使用仅包含新号码的数组创建。

2 个答案:

答案 0 :(得分:4)

您可以使用JSON转换器。特别是,您希望在分支上执行update

val transformer = (__ \ "viewedTaskIds").json.update(
    __.read[JsArray].map(_.append(JsNumber(5)))
)

这将查找包含要更新的数组的分支。 update接受Reads[A <: JsValue]来转换价值。我们将其视为JsArray,然后map将其添加JsNumber(5),如果成功的话。

然后我们需要做的就是将变换器应用于JsValue

val js = Json.parse("""{
    "foo": "bar",
    "viewedTaskIds": [1, 2, 3, 4]
}""")

scala> js.transform(transformer)
res6: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"foo":"bar","viewedTaskIds":[1,2,3,4,5]},/viewedTaskIds)

如果您想提供分支有错误的空数组,可以将orElse添加到变换器并提供Reads.pure(JsArray())以确保它存在。

val transformer = (__ \ "viewedTaskIds").json.update(
    __.read[JsArray].orElse(Reads.pure(JsArray())).map(_.append(JsNumber(5)))
)

不幸的是,当路径根本不存在时,我很难找到一个提供空数组的好解决方案。 orElse无法正常工作,因为路径不在变压器的顶层。有效的是提供一个后备变压器。它不是很漂亮,而且它的形式很粗糙,但它有效:

val fallback = __.json.update((__ \ "viewedTaskIds").json.put(JsArray(Seq(JsNumber(5)))))

scala> js.transform(transformer).orElse(js.transform(fallback))
res19: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"foo":"bar","viewedTaskIds":[5]},)

答案 1 :(得分:0)

如果这是重复操作,您应该使用update创建转换器并使用transform进行调用。您可以阅读有关变形金刚here的更多信息。

如果这是一次性操作,您可能希望使用JsObjectJsArray上的基本操作。具体来说,您可以使用JsObject+-添加和删除键值对,将元素附加到JsArray :+,并合并{{ 1}}与JsObjects

++

如评论中所述,如果JSON没有按预期格式化,其中一些操作(例如val model = Json.parse("""{ "foo": "bar", "viewedTaskIds": [1, 2, 3, 4] }""").as[JsObject] val newIds = (model \ "viewedTaskIds").as[JsArray] :+ JsNumber(5) val newModel = model - "viewedTaskIds" + ("viewedTaskIds" -> newIds) //alternative to using - and +: val newModel = model ++ Json.obj("viewedTaskIds" -> newIds) //one liner: val newModel = model ++ Json.obj("viewedTaskIds" -> ((model \ "viewedTaskIds").as[Seq[Int]] :+ 5)) )将抛出异常。变形金刚更适合处理这种情况,这里的技术应谨慎使用。