我在疯狂尝试解析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))
,否则实例化None
。
你会如何处理?
答案 0 :(得分:10)
我很确定有更好的方式来做你想做的事情,而不是我要发布的内容,但现在已经很晚了,我现在无法理解。我假设只是改变你正在消费的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, lastName: 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。
答案 1 :(得分:4)
您的javascript对象应该与您的案例类的结构相匹配。 Position
也需要有一个json阅读器。
val jsonStr = """{ "personFirstName": "FirstName",
"personLastName": "LastName",
"position":{
"lat": null,
"lon": null
}
}"""
case class Person( firstName: String, lastName: String, p: Option[Position] )
object Person {
implicit val reader = (
(__ \ 'personFirstName ).read[String] ~
(__ \ 'personLastName ).read[String] ~
(__ \ 'position ).readNullable[Position]
)(Person.apply _)
}
case class Position( val lat: Double, val lon: Double)
object Position {
implicit val reader = (
(__ \ 'lat ).read[Double] ~
(__ \ 'lon ).read[Double]
)(Position.apply _)
}
如果json对象中Position
的任何一个字段为空/缺少,则将其解析为None
。所以,jsonStr.as[Person] = Person("FirstName", "LastName", None)