【发布时间】:2015-03-20 19:17:22
【问题描述】:
我有只包含字符串或字符串集合的案例类,并希望将它们转换为具有相应字段名称的 JSON 对象以及用于表示类型的附加字段。
sealed trait Item
case class ProductX(a: String, b: String) extends Item
case class ProductY(a: String, b: String) extends Item
case class CollX(els: List[String]) extends Item
case class CollY(els: List[String]) extends Item
大多数库都对案例类有特殊支持,但似乎从来没有办法将它与附加类型字段结合使用来消除同构案例的歧义,我不得不退回到更底层的描述.
到目前为止,我已经尝试过 spray-json 和 argonaut,我得到的样板文件比我的简单使用场景所证明的要多得多:
// spray-json
implicit object CollXJsonFormat extends RootJsonFormat[CollX] {
def write(ss: CollX) = JsObject(
"type" -> JsString("CollX"),
"els" -> JsArray(ss.els.map(JsString(_)): _*)
)
def read(value: JsValue) = {
value.asJsObject.getFields("type", "els") match {
case Seq(JsString("CollX"), JsArray(els)) =>
CollX(els.toList.map({
case JsString(s) => s
case _ => throw new DeserializationException("JsString expected")
}))
case _ => throw new DeserializationException("CollX expected")
}
}
}
对于 argonaut,我什至不知道如何匹配类型字段,因为 DecodeResult 没有过滤方法:
// argonaut
implicit def CollXCodec: CodecJson[CollX] =
CodecJson(
(px: CollX) =>
("type" := "CollX") ->:
("els" := px.els) ->:
jEmptyObject,
c => for {
t <- (c --\ "type").as[String]
els <- (c --\ "els").as[List[String]]
} yield CollX(els))
是否有另一个库可以更好地处理这个问题,或者我忽略的其中一个库中有一些功能会显着减少样板代码?
【问题讨论】:
-
我过去成功使用过json4s。
-
我建议远离反射型 JSON 库,例如 json4s 和 lift-json。查看play-json-variants,了解如何以更简洁的方式处理此问题的一个很好的示例。
-
感谢@TravisBrown,一针见血!
标签: json scala spray-json argonaut