我在疯狂尝试解析Play Framework 2.2中的这个
JSON结构:
val jsonStr = """{ personFirstName: "FirstName",personLastName: "LastName" positionLat: null,positionLon: null }"""
我有2个案例类:
case class Position( val lat: Double,val lon: Double) case class Person( firstName: String,lastName: String,p: Option[Position] )
如您所见,在Person案例类中,Position不是强制性的.
我试图用这样的东西得到一个Person的实例
implicit val reader = ( (__ \ 'personFirstName ).read[String] ~ (__ \ 'personLastName ).read[String] ~ ( (__ \ 'positionLat ).read[Double] ~ (__ \ 'positionLon ).read[Double] )(Position) )(Person)
但我很快意识到我不知道如何处理Option [Position]对象:如果指定’lat’和’lon’并且不是null,则意图是实例化Some(Position(lat,lon)),否则实例化无.
你会怎么处理?
解决方法
我很确定有一种更好的方式来做你想做的事情而不是我要发布的内容,但它已经很晚了,我现在无法理解.我假设只是改变您正在使用的JSON结构不是一个选项.
你可以提供一个构建器函数,它为lat / lon提供两个可选的双精度数,并且如果它们都存在则产生一个位置.
import play.api.libs.functional.Syntax._ import play.api.libs.json._ val jsonStr = """{ "personFirstName": "FirstName","personLastName": "LastName","positionLat": null,"positionLon": null }""" case class Position(lat: Double,lon: Double) case class Person( firstName: String,p: Option[Position] ) object Person { implicit val reader = ( (__ \ "personFirstName" ).read[String] and (__ \ "personLastName" ).read[String] and ( (__ \ "positionLat" ).readNullable[Double] and (__ \ "positionLon" ).readNullable[Double] )((latOpt: Option[Double],lonOpt: Option[Double]) => { for { lat <- latOpt ; lon <- lonOpt} yield Position(lat,lon) }) )(Person.apply _) } Json.parse(jsonStr).validate[Person] // yields JsSuccess(Person(FirstName,LastName,None),)
另外,请注意,要成为有效的JSON,您需要quote the data keys.