2

我正在尝试使用 Play 中的 Json 库序列化地图。我写了自己的 Writes,因为 Maps 没有。

import play.api.libs.json.Json._
import play.api.libs.json._

object NestedArray extends App {
  val m: Map[Int, String] = Map(1 -> "one", 2 -> "two")

  implicit val mWrites = new Writes[Map[Int, String]] {
    def writes(m: Map[Int, String]) = arr(
      m.keys.map(k => {
        obj("key" -> k.toString,
          "value" -> m(k)
        )
      })
    )
  }

  val j = toJson[Map[Int, String]](m)
  println(prettyPrint(j))
}

输出是这样的:

[ [ {
  "key" : "1",
  "value" : "one"
}, {
  "key" : "2",
  "value" : "two"
} ] ]

如您所见,项目周围有两对 [ ]。当我在地图周围使用 Wrapper 类时,我只得到一对 []。

case class Wrap(m: Map[Int, String])
val w = new Wrap(m)

implicit val wrapWrites = new Writes[Wrap] {
  def writes(w: Wrap) = obj(
    "m" -> w.m.keys.map(k => {
      obj("key" -> k.toString,
        "value" -> w.m(k)
      )
    })
  )
}

val j2 = toJson[Wrap](w)
println(prettyPrint(j2))

输出:

{
  "m" : [ {
    "key" : "1",
    "value" : "one"
  }, {
    "key" : "2",
    "value" : "two"
  } ]
}

有没有办法在没有包装类的情况下实现这一目标?

4

2 回答 2

1

Json.arr从它的参数列表中创建一个 JSON 数组。由于第一个参数本身是一个序列,因此结果是一个序列的序列。

例如

scala> Json.arr(1,2,3)
res1: play.api.libs.json.JsArray = [1,2,3]

scala> Json.arr(List(1,2,3))
res2: play.api.libs.json.JsArray = [[1,2,3]]

使用 toJson 删除对 Iterable的调用arr并将其直接转换为 JSON 会删除嵌套数组

import play.api.libs.json.Json._
import play.api.libs.json._

object NestedArray extends App {
  val m: Map[Int, String] = Map(1 -> "one", 2 -> "two")

  implicit val mWrites = new Writes[Map[Int, String]] {
    def writes(m: Map[Int, String]): JsValue = 
      Json.toJson(m.keys.map(k => {
        obj("key" -> k.toString,
          "value" -> m(k)
        )
      }))
  }

  val j = toJson[Map[Int, String]](m)
  println(prettyPrint(j))
}
于 2014-10-28T01:43:37.090 回答
0

Play 确实提供了一个Writes[Map[String, _]],您可以根据自己的用途进行调整。似乎没有必要创建结构来表示一系列键值对,而这已经是 JSON 对象。请参阅我对类似问题的回答:How to serialize a Map[CustomType, String] to JSON

于 2014-10-28T13:09:36.393 回答