次の方法で実行できます。
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)
ただし、分離して作成することをお勧めします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)
編集:単純なケースクラスの場合、次のことが可能です:
implicit val socialUserReads = Json.format[SocialUser]
implicit val userDetailsReads = Json.format[UserDetails]
implicit val combinedUserReads = Json.format[CombinedUser]
ここでは、JSON 読み取りなどの非常に包括的な紹介を行います。
部分オブジェクトはどうですか?コンストラクターのすべてのフィールドに入力したくない場合は、空を渡すか、コンストラクターなどをオーバーロードできますか?
使用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),)