Question

Given lift-json 2.0 and the following Scala classes & sealed trait:

sealed trait Location

case class Coordinate(latitude: Double,
                      longitude: Double) extends Location

case class Address(...) extends Location

I'd like to be able to deserialize a Location object without determining the concrete implementation:

deserialize[Location](""" { "latitude":0.0, "longitude":0.0 } """)

should produce the equivalent of:

val location: Location = Coordinate(0.0, 0.0)

Any way of doing this?

Was it helpful?

Solution

This may not be what you want, but with:

implicit val formats = net.liftweb.json.DefaultFormats
  .withHints(ShortTypeHints(List(classOf[Geo], classOf[Address])))

enables you to write

val loc: Location = read(write(Geo(0.0, 0.0)))

However your json then gets a TypeHint:

{"jsonClass":"Geo","latitude":0.0,"longitude":0.0}

This formats can be played with somewhat, here is a nice post about type hints.

OTHER TIPS

Lift-Json won't automatically detect a subclass to deserialize to because there is no straight forward way to do that. You might have 2 subclasses of Location that accept latitude and longitude constructor parameters, or some other ambiguity.

Type hints are definitely one way to go. If you don't want to muddy up your JSON with scala specific info though, you can also deserialize the string representation to a JValue, then inspect the structure to determine which class to bind to.

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)
  }
}

If you can't choose your type based on arity, that would be more complicated, but you get the general idea.

@"Dave Whittaker" and @"Rin malavi" are right in general. Also, if you want a temporary solution, you may use:

str.extractOpt[Address] getOrElse str.extract[Coordinate]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top