在Scala中,如何为Map [IndexedSeq [String],Int]编写一个高效的json格式化程序?

时间:2016-02-22 19:36:07

标签: json scala playframework format playscalajs

我认为scala中没有Map [IndexedSeq [String],Int]的默认格式(对吧?)所以我编写了自己的格式如下,但是速度非常慢。有更好的方法吗?

class IndexedSeqToIntMapFormat() extends Format[Map[IndexedSeq[String], Int]] {

 def writes(o: Map[IndexedSeq[String], Int]): JsValue = {
   val mapItems: Seq[String] = o.toSeq.map{case (rowKey, index) => (index.toString +: rowKey).mkString(",")}
   Json.obj("items" -> Json.toJson(mapItems))
 }

 def reads(json: JsValue): JsResult[Map[IndexedSeq[String], Int]] = {
   val mapItemsAsString: IndexedSeq[String] = (json \ "items").as[IndexedSeq[String]]
   val map: Map[IndexedSeq[String], Int] = mapItemsAsString.map(itemAsString => {
     val item: IndexedSeq[String] = itemAsString.split(",").toIndexedSeq
     val rowKey: IndexedSeq[String] = item.tail
     val rowIndex: Int = item.head.toInt
     (rowKey, rowIndex)
   }).toMap

   JsSuccess(map)
 }
}

谢谢!

1 个答案:

答案 0 :(得分:2)

无法确定以下方法是否明显快于您的方法,但根据我的理解,它更符合"精神" JSON。在JSON序列化中,每个对象及其所有子对象和属性都应按它们的名称命名。在我看来,复杂对象的自定义字符串序列化列表不是真正的JSON表示。

在"适当的" JSON方式至少应该在解析中节省一些时间,因为它不需要对字符串进行额外的解析工作,但已经在所需的位置提供了所有数据。 代码看起来更具可读性: - )

生成的JSON应如下所示:

"items": [
  { "keySeq": [ "key1", "key2", "key3" ], "value": 42 },
  { "keySeq": [ "key4", "key5" ], "value": 123 },
  { "keySeq": [ "key6", "key7", "key7" ], "value": 650 }
]

格式化程序可能是这样的:

class IndexedSeqToIntMapFormat() extends Format[Map[IndexedSeq[String], Int]] {

  def writes(m: Map[IndexedSeq[String], Int]): JsValue = {
    val objs = m.toSeq.map { case (keySeq, value) =>
      Json.obj("keySeq" -> Json.toJson(keySeq), "value" -> JsNumber(value))
    }
    Json.obj("items" -> JsArray(objs))
  }

  def reads(json: JsValue): JsResult[Map[IndexedSeq[String], Int]] = {
    val seq = (json \ "items").as[Seq[JsValue]] map { obj =>
      ( (obj \ "keySeq").as[IndexedSeq[String]], (obj \ "value").as[Int] )
    }
    JsSuccess(seq.toMap)
  }
}

顺便说一下,出于好奇 - 你能告诉我你需要一张这样的地图吗?