在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,所以我认为这种方法相当昂贵。我怎么能这样做?
答案 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,但会导致与地图发生冲突。)