Как в Scala написать эффективный форматер json для Map[IndexedSeq[String], Int]?

Я думаю, что нет никакого формата по умолчанию для Map[IndexedSeq[String], Int] в scala (верно?). Поэтому я написал свой собственный формат следующим образом, однако он очень медленный. Есть лучший способ сделать это?

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 ответ

Решение

Не могу точно сказать, является ли следующий подход значительно более быстрым, чем ваш, но, насколько я понимаю, он намного больше соответствует "духу" 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)
  }
}

Кстати, просто из любопытства - можете ли вы сказать мне, в каком контексте вам нужна такая карта?

Другие вопросы по тегам