How to render a sorted map in json libraries (of play framework)?

170 Views Asked by At

I need to render a sorted map by a user-defined type. SortedMap[X, Seq[Y]]

Json library should render the map as ordered by the X.name

case class X(order: Int, name: String) extends Ordered[X]

Assume I have X(1, "James"), X(2, "Mel"), X(3, "Ashley"). The output map should be

"James" : Seq(Y)

"Mel" : Seq(Y)

"Ashley": Seq(Y)

The inMap is correctly sorted (as viewed by the debugger), but after the rendering, the sorting order(X.order) is lost. Probably due to the toSeq. Any ideas?

implicit val myWrites = new Writes[SortedMap[X, Seq[Y]]] {
    def writes(inMap: SortedMap[X, Seq[Y]]): JsValue =
      Json.obj(inMap.map {case (s, o) =>
        val r: (String, JsValueWrapper) = s.name() -> Json.toJson(o)
        r
      }.toSeq:_*)
  }
1

There are 1 best solutions below

0
On BEST ANSWER

So...

  • I never meet the word "render" used as "convert to"
  • ordering by key original key in SortedSet is lost after mapping because you change the key type so the result is ordered by a new key type (here: String)
  • if you want to preserve the order of items in between mapping I would suggest using ListMap
  • though in your particular case you can do away with Seq of tuples, as at the end of the day, this is what you need to produce
implicit val myWrites: Writes[SortedMap[X, Seq[Y]]] = new Writes[SortedMap[X, Seq[Y]]] {
  def writes(inMap: SortedMap[X, Seq[Y]]): JsValue =
    Json.obj(inMap.toSeq.map { case (s, o) =>
      s.name() -> Json.toJson(o)
    }:_*)
}