播放Json写道:Scala Seq到Json对象

时间:2016-03-01 17:39:43

标签: json scala playframework playframework-2.0

在Scala中,我有以下数据结构(Item名称在同一Container内始终是唯一的):

case class Container(content: Seq[Item])
case class Item(name: String, elements: Seq[String])

示例实例:

val container = Container(Seq(
    Item("A", Seq("A1", "A2")),
    Item("B", Seq("B1", "B2"))
))

我想要做的是定义一个产生以下JSON的Writes[Container]

{
    "A": ["A1", "A2"],
    "B": ["B1", "B2"]
}

猜测可能的解决方案是将Container(Seq[Item])转换为Map[String, Seq[String]],其中每个键对应一个项目的名称和项目的值& #39; s元素并让API完成其余的工作(可能是对地图的隐式写入,至少在读取JSON时就是这种情况)。

但是:这种方法为每个Map创建一个新的Container,除了生成JSON之外别无其他目的。有很多Container个实例需要转换为JSON,所以我认为这种方法相当昂贵。我怎么能这样做?

1 个答案:

答案 0 :(得分:2)

我认为你不一定要担心这里的速度(或者至少在担心它之前验证它是一个问题),转换到地图可能是最简单的选择。另一种可能不会更好的替代方案是:

val customWrites: Writes[Container] = new Writes[Container] {
  override def writes(container: Container): JsValue = {
    val elems = container.content.map(
        elem => elem.name -> Json.toJsFieldJsValueWrapper(elem.elements))
    Json.obj(elems: _*)
  }
}

(显式转换为JsValueWrapper - 这通常是隐含的 - 在这种情况下似乎是必要的,原因是我不完全理解或有时间深入研究。This answer有一些细节。)

此方法的一个优点是它将处理具有重复名称的Item个对象(当然这是合法的JSON,但会导致与地图发生冲突。)