使用组合器播放2.2 JSON读取:如何处理嵌套的可选对象?

我在疯狂尝试解析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.

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...