鉴于lift-json
2.0以及以下Scala类和& 密封特质:
sealed trait Location
case class Coordinate(latitude: Double,
longitude: Double) extends Location
case class Address(...) extends Location
我希望能够在不确定具体实现的情况下反序列化Location对象:
deserialize[Location](""" { "latitude":0.0, "longitude":0.0 } """)
应该产生相当于:
val location: Location = Coordinate(0.0, 0.0)
任何方式这样做?
答案 0 :(得分:2)
这可能不是你想要的,但是:
implicit val formats = net.liftweb.json.DefaultFormats
.withHints(ShortTypeHints(List(classOf[Geo], classOf[Address])))
可以让你写
val loc: Location = read(write(Geo(0.0, 0.0)))
然而你的json会得到一个TypeHint:
{"jsonClass":"Geo","latitude":0.0,"longitude":0.0}
这种格式可以稍微播放,这里是nice post about type hints.
答案 1 :(得分:1)
Lift-Json不会自动检测要反序列化的子类,因为没有直接的方法可以做到这一点。您可能有2个Location子类,它们接受纬度和经度构造函数参数,或者其他一些歧义。
类型提示绝对是一种方法。如果你不想使用scala特定信息来混淆你的JSON,你也可以将字符串表示反序列化为JValue,然后检查结构以确定要绑定到哪个类。
def location(str: String): Location = {
val jv = JsonParser.parse(string)
jv match {
case jo: JObject if jo.children.size == 2 => Extraction.extract[Coordninate](jo)
case _ => Extraction.extract[Address](jv)
}
}
如果你不能根据arity选择你的类型,那会更复杂,但你会得到一般的想法。
答案 2 :(得分:1)
@“Dave Whittaker”和@“Rin malavi”一般都是正确的。此外,如果您需要临时解决方案,可以使用:
str.extractOpt[Address] getOrElse str.extract[Coordinate]