Play框架:如何按字母顺序排序JSON

5

给定以下JSON...

{
   "z": 100,
   "b": 50,
   "q": 12
}

如何按字母顺序对键进行排序?

3个回答

6

很简单,但是(显然)我们需要确保拥有一个JsObject

val js = Json.parse("""{
   "z": 100,
   "b": 50,
   "q": 12
}""")

val jsObject = js.as[JsObject] // Not actually safe, but bear with me

这些字段会被简单地存储在名为fields的字段中,格式为Seq[(String, JsValue)]

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}

4

我遇到了与 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
}

0

这是我使用的可行方案(已测试):

  • Scala 版本:2.11.8
  • Play 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}

只是供参考:这是我在接受的答案中遇到的错误:

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)) })
                                                                                                 ^

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接