Play Framework:如何按字母顺序对 JSON 进行排序
Play Framework: How to sort JSON alphabetically
鉴于以下 JSON...
{
"z": 100,
"b": 50,
"q": 12
}
如何按字母顺序对键进行排序?
很简单,但是(显然)我们需要确保我们有一个 JsObject
.
val js = Json.parse("""{
"z": 100,
"b": 50,
"q": 12
}""")
val jsObject = js.as[JsObject] // Not actually safe, but bear with me
这些字段只是作为 Seq[(String, JsValue)]
.
存储在名为 fields
的字段中
scala> jsObject.fields
res5: Seq[(String, play.api.libs.json.JsValue)] = ListBuffer((z,100), (b,50), (q,12))
我们可以使用相同的字段创建一个新的 JsObject
,但已排序。
scala> JsObject(jsObject.fields.sortBy(_._1))
res6: play.api.libs.json.JsObject = {"b":50,"q":12,"z":100}
前面我提到使用as[JsObject]
是不安全的,因为如果我们的JsValue
实际上是一个数组或者字符串,它会抛出异常。在这里处理 JsValue
的更安全的方法是对 JsObject
进行模式匹配并对其进行排序,而不对任何其他类型执行任何操作。创建一个递归排序所有键的方法很简单:
def sortJs(js: JsValue): JsValue = js match {
case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
case _ => js
}
val js = Json.parse("""{
"z": 100,
"b": {"k": 1, "j": 3, "i": 98},
"q": 12
}""")
scala> sortJs(js)
res8: play.api.libs.json.JsValue = {"b":{"i":98,"j":3,"k":1},"q":12,"z":100}
这对我有用(经过测试):
- Scala 版本:2.11.8
- 播放json版本:2.6.10
scala> val js = Json.parse("""{
| "z": 100,
| "b": 50,
| "q": 12
| }""")
js: play.api.libs.json.JsValue = {"z":100,"b":50,"q":12}
scala> def sortJs(js: JsValue): JsValue = js match {
| case o: JsObject =>
| JsObject(o.fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
| case _ => js
| }
sortJs: (js: play.api.libs.json.JsValue)play.api.libs.json.JsValue
scala> sortJs(js)
res1: play.api.libs.json.JsValue = {"b":50,"q":12,"z":100}
只是 FTR:这是我在接受答案时遇到的错误:
scala> def sortJs(js: JsValue): JsValue = js match {
| case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
| case _ => js
| }
<console>:16: error: value sortBy is not a member of scala.collection.Map[String,play.api.libs.json.JsValue]
case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
^
<console>:16: error: type mismatch;
found : Any
required: play.api.libs.json.JsValue
case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
^
我 运行 进入了 Yuchen 所接受的相同问题。这就是我让它工作的方式:
def sortJs(js: JsValue): JsValue = js match {
case JsObject(fields) => JsObject(fields.toSeq.sortBy(_._1).map { case (key, value) => (key, sortJs(value.asInstanceOf[JsValue]))})
case _ => js
}
以上版本不处理递归排序 JsArray。这个版本可以解决这个问题。
def sortJs(js: JsValue): JsValue = js match {
case JsObject(fields) => JsObject(fields.toSeq.sortBy(_._1).map { case (key, value) => (key, sortJs(value.asInstanceOf[JsValue])) })
case JsArray(array) => JsArray(array.map(e => sortJs(e)))
case other => other
}
鉴于以下 JSON...
{
"z": 100,
"b": 50,
"q": 12
}
如何按字母顺序对键进行排序?
很简单,但是(显然)我们需要确保我们有一个 JsObject
.
val js = Json.parse("""{
"z": 100,
"b": 50,
"q": 12
}""")
val jsObject = js.as[JsObject] // Not actually safe, but bear with me
这些字段只是作为 Seq[(String, JsValue)]
.
fields
的字段中
scala> jsObject.fields
res5: Seq[(String, play.api.libs.json.JsValue)] = ListBuffer((z,100), (b,50), (q,12))
我们可以使用相同的字段创建一个新的 JsObject
,但已排序。
scala> JsObject(jsObject.fields.sortBy(_._1))
res6: play.api.libs.json.JsObject = {"b":50,"q":12,"z":100}
前面我提到使用as[JsObject]
是不安全的,因为如果我们的JsValue
实际上是一个数组或者字符串,它会抛出异常。在这里处理 JsValue
的更安全的方法是对 JsObject
进行模式匹配并对其进行排序,而不对任何其他类型执行任何操作。创建一个递归排序所有键的方法很简单:
def sortJs(js: JsValue): JsValue = js match {
case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
case _ => js
}
val js = Json.parse("""{
"z": 100,
"b": {"k": 1, "j": 3, "i": 98},
"q": 12
}""")
scala> sortJs(js)
res8: play.api.libs.json.JsValue = {"b":{"i":98,"j":3,"k":1},"q":12,"z":100}
这对我有用(经过测试):
- Scala 版本:2.11.8
- 播放json版本:2.6.10
scala> val js = Json.parse("""{
| "z": 100,
| "b": 50,
| "q": 12
| }""")
js: play.api.libs.json.JsValue = {"z":100,"b":50,"q":12}
scala> def sortJs(js: JsValue): JsValue = js match {
| case o: JsObject =>
| JsObject(o.fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
| case _ => js
| }
sortJs: (js: play.api.libs.json.JsValue)play.api.libs.json.JsValue
scala> sortJs(js)
res1: play.api.libs.json.JsValue = {"b":50,"q":12,"z":100}
只是 FTR:这是我在接受答案时遇到的错误:
scala> def sortJs(js: JsValue): JsValue = js match {
| case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
| case _ => js
| }
<console>:16: error: value sortBy is not a member of scala.collection.Map[String,play.api.libs.json.JsValue]
case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
^
<console>:16: error: type mismatch;
found : Any
required: play.api.libs.json.JsValue
case JsObject(fields) => JsObject(fields.sortBy(_._1).map { case (k, v) => (k, sortJs(v)) })
^
我 运行 进入了 Yuchen 所接受的相同问题。这就是我让它工作的方式:
def sortJs(js: JsValue): JsValue = js match {
case JsObject(fields) => JsObject(fields.toSeq.sortBy(_._1).map { case (key, value) => (key, sortJs(value.asInstanceOf[JsValue]))})
case _ => js
}
以上版本不处理递归排序 JsArray。这个版本可以解决这个问题。
def sortJs(js: JsValue): JsValue = js match {
case JsObject(fields) => JsObject(fields.toSeq.sortBy(_._1).map { case (key, value) => (key, sortJs(value.asInstanceOf[JsValue])) })
case JsArray(array) => JsArray(array.map(e => sortJs(e)))
case other => other
}