如何使用scala中的lift-json在不知道具体类型的情况下反序列化?

时间:2013-11-19 07:28:06

标签: json scala lift json-deserialization lift-json

鉴于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)

任何方式这样做?

3 个答案:

答案 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]