玩! scala的JSON转换Slick一对多关系

时间:2013-11-03 18:01:07

标签: scala slick playframework-2.2

阅读this question

我想知道如何生成Directorate及其ServicesAreas集合的JSON值。如果我们使用Play! 2.2提供的新的初始机制,我们只会格式化案例类理事会。

简单的答案是单独格式化案例类和列表(2 JSON AST)并使用Play JSON API组合它们来构建单个树吗?

非常感谢您的灯光

更新1: 当我写关于联合收割机时,我正在考虑写组合器。 Write[Directorate] and Write[Seq[ServicesArea]]? 或者也许在使用Slick查询时,使用Directorate基本属性+ Seq of ServiceAreas构建新的案例类更容易吗?

1 个答案:

答案 0 :(得分:2)

我会说你有两个很好的选择,也没有与你使用Slick有关(这很好,如何在数据库中存储东西不应该与你如何将它变成某种序列化格式紧密结合,对吧?)。

使用case类和Json.format宏代表使用相应类结构的json格式。您当然可以从“模型”类结构中创建单独的类层次结构,因为您可能希望以不同的方式构造事物,隐藏字段等。避免进行模型重构也许是好的,例如,更改属性名称会更改json格式,特别是如果你有json的外部用户。

另一种选择是在一些通用数据结构中收集数据,例如List[(Directorate, Seq[ServicesArea])]Map[(Directorate, Seq[ServicesArea])]并创建Writes[thattype]或者甚至可以像使用json一样简单api用于构建您想要的json格式,如下所示:

...
JsArray(entries.map { case (directorate, serviceAreas) =>
  Json.obj(
    "somekey" -> directorate.someProp,
    "areas" -> JsArray(serviceAreas.map { area => 
      Json.obj(
        "areakey" -> area.something
      )}
  )
})
...

当然使用组合器api来创建写操作也很简单,可能更简洁但更难理解(除非你以前使用过combinator api),这只是另一种实现相同想法的方法。

...
implicit val serviceAreaWrites: Writes[ServiceArea] = (
  (__ \ "areakey").write[String] and 
  (__ \ "someotherkey").write[String]
)(unlift(ServiceArea.unapply)) 
// note that this must return the exact list of fields you have listed

implicit val directorateWrites: Writes[(Directorate, Seq[ServiceArea])] = (
  (__ \ "somekey").write[String] and 
  (__ \ "areas").write[Seq[ServiceArea]]
)(unlift(Tuple2.unapply[Directorate, Seq[ServiceArea]))

这两者都不是“正确(tm)”的方式,你必须考虑你的应用程序中的优缺点,并选择最合适的。< / p> 祝你好运!