简体   繁体   English

Play Framework 2.1.1 Json编写嵌套对象

[英]Play Framework 2.1.1 Json Writes nested objects

I've been trying to get my head around this all afternoon to no avail, Play 2.1.1 overhauled how the Json reads and writes work. 我整个下午一直试图让自己的头脑无所适从,Play 2.1.1彻底改变了Json如何读写作品。

Basically I have a wrapper object that looks like: 基本上我有一个包装器对象,看起来像:

case class CombinedUser(user: SocialUser, userdetails: UserDetails)

as you can see it contains 2 classes that I want to serialize and deserialize to json. 你可以看到它包含2个我想要序列化和反序列化为json的类。

But I don't understand how I can get and set the fields in the subclasses using the new design. 但我不明白如何使用新设计获取和设置子类中的字段。

For example 例如

implicit val combinedUser2Reads = (
  (__ \ "email").read[String] and
  (__ \ "providerid").read[String] and
  (__ \ "firstname").read[String] and
  (__ \ "lastname").read[String] and
  (__ \ "fullname").read[String] and
  (__ \ "avatarurl").read[String] and
  (__ \ "address1").read[String] and
  (__ \ "address2").read[String] and
  (__ \ "address3").read[String] and
  (__ \ "city").read[String] and
  (__ \ "country").read[String] and
  (__ \ "phone").read[String] and
  (__ \ "publickey").as[String]
)(CombinedUser2.apply _)

I want a json blob that has most of the subclasses fields, all strings. 我想要一个包含大多数子类字段的json blob,所有字符串。

Because it uses the apply stuff, I don't see how I can create the subclasses before the mapping. 因为它使用了apply东西,所以我看不出如何在映射之前创建子类。

Any help or guidance is much appreciated. 非常感谢任何帮助或指导。

Thanks 谢谢

Tom 汤姆

You can do it this way: 你可以这样做:

case class SocialUser(firstName: String, lastName: String)
case class UserDetails(avatarUrl: String, phone: String)
case class CombinedUser(user: SocialUser, userDetails: UserDetails)  
implicit val combinedUserReads: Reads[CombinedUser] = (
  (__ \ "user").read((
    (__ \ "firstName").read[String] and
    (__ \ "lastName").read[String]
  )(SocialUser)) and
  (__ \ "userDetails").read((
    (__ \ "avatarUrl").read[String] and
    (__ \ "phone").read[String]
  )(UserDetails))
)(CombinedUser)

However its better to create separated Reads : 但是创建单独的Reads更好:

implicit val socialUserReads = (
  (__ \ "firstName").read[String] and
  (__ \ "lastName").read[String]
)(SocialUser)    
implicit val userDetailsReads = (
  (__ \ "avatarUrl").read[String] and
  (__ \ "phone").read[String]
)(UserDetails)
implicit val combinedUserReads: Reads[CombinedUser] = (
  (__ \ "user").read[SocialUser] and
  (__ \ "userDetails").read[UserDetails]
)(CombinedUser)

Edit: for simple case classes, its possible to do : 编辑:对于简单的案例类, 它可以做

implicit val socialUserReads = Json.format[SocialUser]
implicit val userDetailsReads = Json.format[UserDetails]
implicit val combinedUserReads = Json.format[CombinedUser]

Here is quite comprehensive introduction to JSON Reads and more. 以下是对JSON Reads等的全面介绍。

How about partial objects? 部分物体怎么样? If I don't want to fill in every field in the constructor, can I pass empties or do I overload the constructor or similar? 如果我不想填写构造函数中的每个字段,我可以通过清空,还是重载构造函数或类似的?

Use Option : 使用Option

case class CombinedUser(user: SocialUser, userDetails: Option[UserDetails])
//reads
implicit val combinedUserReads: Reads[CombinedUser] = (
  (__ \ "user").read[SocialUser] and
  (__ \ "userDetails").readOpt[UserDetails]
)(CombinedUser)
//writes
implicit val combinedUserWrites: Writes[CombinedUser] = (
  //socialUserWrites and userDetailsWrites must be in scope
  (__ \ "user").write[SocialUser] and
  (__ \ "userDetails").write[Option[UserDetails]]
)(unlift(CombinedUser.unapply))

val json = Json.obj(
  "user" -> Json.obj(
    "firstName" -> "Homer",
    "lastName" -> "Simpson"
  )
)
Json.fromJson[CombinedUser](json)
//JsSuccess(CombinedUser(SocialUser(Homer,Simpson),None),)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM