6

我正在疯狂地尝试在 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 案例类中不是强制性的。

我试图使用类似这样的东西来获取 Person 的实例

implicit val reader = (
  (__ \ 'personFirstName ).read[String] ~
  (__ \ 'personLastName ).read[String] ~
  ( (__ \ 'positionLat ).read[Double] ~
    (__ \ 'positionLon ).read[Double] )(Position)
)(Person)

但我很快意识到我不知道如何处理该对象:如果指定了 'lat' 和 'lon' 并且不为 null,则Option[Position]意图是实例化 a ,否则实例化。Some(Position(lat,lon))None

你会怎么处理呢?

4

2 回答 2

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,您需要引用数据键

于 2013-10-20T22:45:49.250 回答
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)

于 2013-10-20T22:54:41.973 回答