【问题标题】:Play Json Writes: Scala Seq to Json Object播放 Json 写入:Scala Seq 到 Json 对象
【发布时间】:2016-03-01 17:39:42
【问题描述】:

在 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"))
))

我想做的是定义一个Writes[Container],它会产生以下JSON:

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

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

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

【问题讨论】:

    标签: json scala playframework playframework-2.0


    【解决方案1】:

    我认为您不必担心这里的速度(或至少在担心它之前验证这是一个问题),并且转换为地图可能是最简单的选择。另一种可能效果不会更好的替代方法是:

    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,但会导致与地图发生冲突。)

    【讨论】:

    • 您对性能的看法可能是正确的。但是,您的解决方案不仅允许重复名称,而且还保留了更好的元素顺序,谢谢!
    猜你喜欢
    • 2013-01-11
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2021-03-07
    • 2015-12-23
    • 1970-01-01
    相关资源
    最近更新 更多