gpt4 book ai didi

json - 如何使用 play-json 对 JsArray 进行排序

转载 作者:行者123 更新时间:2023-12-03 09:23:25 28 4
gpt4 key购买 nike

简单问题:

如何使用 play-json (2.3.x) 对某些 JsValue 中的所有 JsArray 进行排序(递归)?

我的用例:

考虑一个在内部使用 Set[String] 的应用,当请求数据时,输出 JSON 将集合序列化为 JSON 数组。顺序并不重要。

现在,如果有人想编写一些测试来覆盖此功能,因为项目的顺序并不重要(毕竟它是一个集合。内部和概念上),我想要检查的是所有内容都返回为应该如此,我可能想将响应 JSON 与我显式创建的“预期”JSON 对象进行比较。

正是出于这个原因,我想对 JSON 数组进行排序,并比较 JsValue 的值。如何编写这样的变压器?

编辑:

我已经成功编写了一个能够满足我的需求的转换器,但它不会对某些 JsValue 中的每个 JsArry 进行排序。我将其发布在这里,因为它可能对其他人有用,但这不是我想要的。

val jsonSortTransformer = (__ \ 'fields).json.update(
Reads.JsObjectReads.map{
case JsObject(xs) => JsObject(
xs.map{
case (n,jv) => {
n -> (jv match {
case JsArray(arr) if arr.forall(_.isInstanceOf[JsString]) => JsArray(arr.sortBy(_.as[String]))
case _ => jv
})
}
}
)
}
)

最佳答案

可以使用JsArray上的value属性来获取一个Seq[JsValue],然后任意排序,然后重新创建一个JsArray。例如:

scala> myJsArray
play.api.libs.json.JsArray = ["11","4","5","1","22","2"]

scala> JsArray(myJsArray.value.sortBy(_.as[JsString].value.toInt))
play.api.libs.json.JsArray = ["1","2","4","5","11","22"]

如果您所做的只是尝试比较您所知道的集合的实际值和预期值,您也可以仅在两个属性上使用 value,构建一个 Set并检查是否相等:

Set(actual.value: _*) == Set(expected.value: _*)

或者对它们进行排序:

val sortedSeq: JsArray => Seq[String] = array => array.value.map(_.toString).sorted
sortedSeq(actual) == sortedSeq(expected)

要对任意 JsValue 中的所有 JsArrays 进行递归排序,它可能类似于:

def sortArrays(json: JsValue): JsValue = json match {
case JsObject(obj) => JsObject(obj.toMap.mapValues(sortArrays(_)).toList)
case JsArray(arr) => JsArray(arr.map(sortArrays).sortBy(_.toString))
case other => other
}

scala> myObj
play.api.libs.json.JsValue = {"a":[2,1],"b":[{"c":[3,2]},{"d":[4,3]}],"e":{"f":[5,4]}}

scala> sortArrays(myObj)
play.api.libs.json.JsValue = {"a":[1,2],"b":[{"c":[2,3]},{"d":[3,4]}],"e":{"f":[4,5]}}

关于json - 如何使用 play-json 对 JsArray 进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26889079/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com