PlayJson Scala阅读Nullable Fields

时间:2016-01-26 18:47:59

标签: json scala playframework-2.0

我有一个联系人类,它会将(JsPath \ "contact_name" \ "first_name" )读取为firstName,但(JsPath \ "contact_name")可以为空。
有没有人知道如何为这个案例类做读者?

case class Contact(var firstName: Option[String],
                   var lastName: Option[String])

我的联系人Json是:

{
  "contact_name": {
     "first_name": "hello",
     "last_name": "world"
  },
  "phone_number": "1231231234",
  "email": "test@gmail.com"
}

联系Json,不要使用" contact_name":

{
  "phone_number": "1231231234",
  "email": "test@gmail.com"
}

我希望两个Json能够读取Contact对象。谢谢。

3 个答案:

答案 0 :(得分:1)

假设您的电话号码和电子邮件是联系方式的一部分,可以使用{(1}}来深入搜索路径):

\\

答案 1 :(得分:0)

我确实写过帖子 - http://pedrorijo.com/blog/scala-json/

它接近如何将json读取到case类。具体来说,在最后一个例子中读取json中的可选字段:

case class User(username: String, friends: Int, enemies: Int, isAlive: Option[Boolean])

object User {

  import play.api.libs.functional.syntax._
  import play.api.libs.json._

  implicit val userReads: Reads[User] = (
      (JsPath \ "username").read[String] and
      (JsPath \ "friends").read[Int] and
      (JsPath \ "enemies").read[Int] and
      (JsPath \ "is_alive").readNullable[Boolean]
    ) (User.apply _)
}

它应该足以让你完成它。 此外,如果json是包含所需字段的字符串,则只需编写:

Json.parse(json)

所以,如果fullJson是完整的Json对象(包含那些不需要的字段),你可以用fullJson \ "contact_name"

提取firstName和lastName

答案 2 :(得分:0)

为了简化我已经完成的事情(虽然它确实创建了很多类):

假设:contact_name是可选的,您希望将整个事物折叠为单个案例类Contact

{
  "contact_name": {
     "first_name": "hello",
     "last_name": "world"
  },
  "phone_number": "1231231234",
  "email": "test@gmail.com"
}


case class Contact(firstName: Optional[String], lastName: Optional[String], phoneNumber: String, email: String)

case class RawContactName(firstName: String, lastName: String)
case class RawContact(contactName: Optional[RawContactName], phoneNumber: String, email: String)

implicit val rawContactReads: Reads[RawContact] = (
      (JsPath \ "contact_name").readNullable[RawContactName] and
      (JsPath \ "phone_number").read[String] and
      (JsPath \ "email").read[String]
    ) (RawContact.apply _)

implicit val rawContactNameReads: Reads[RawContactName] = (
      (JsPath \ "first_name").read[String] and
      (JsPath \ "last_name").read[String]
    ) (RawContactName.apply _)

def transformContact(rawContact: RawContact): Contact = {
    val (maybeFirstName, maybeLastName) = rawContact.contactName match {
        case Some(RawContactName(firstName, lastName)) => (Some(firstName), Some(lastName))
        case None => (None, None)
    }
    Contact(maybeFirstName, maybeLastName, rawContact.phoneNumber, rawContact.email)
}

实际上,我有单独的case类来表示每个JSON节点和一个转换器函数,以将Scala JSON表示转换为我的模型类。如果您有重复的值(例如:同一个JSON文档中的多个联系人对象,那么将出现多个first_name元素),这是有效的。虽然在您的具体示例中,最好跳过Raw类并在模型中创建两个案例类:ContactContactName但我想展示一个分隔View模型的通用解决方案({ {1}})来自内部模型。