User の「アドレス」にはアドレスが含まれているため、実際には Map[User, List[Address]] をクライアントに送り返す必要はありません。Json はシリアル化されたユーザー オブジェクトの配列であり、アドレスはその一部です。Map を送り返したい場合は、Json シリアライゼーション コンテキストでは Map[String, List[Address]] 型の方が理にかなっています。List[User] の Json を生成するコードは次のとおりです。出力は次のようになります
[
{
"id": 1,
"name": "John Doe",
"email": "john@email.com",
"addresses": [
{
"id": 1001,
"userId": 1,
"city": "Chicago"
},
{
"id": 1002,
"userId": 1,
"city": "New York"
}
]
},
{
"id": 2,
"name": "Jane Doe",
"email": "jane@email.com",
"addresses": [
{
"id": 1012,
"userId": 1,
"city": "Dallas"
}
]
}
]
コントローラーにあるコードは次のとおりです。Json.toJson で使用される暗黙的な Json フォーマッターがあります。
implicit object PkWrites extends Writes[Pk[Long]] {
def writes(key: Pk[Long]) = Json.toJson(key.toOption)
}
implicit object PkReads extends Reads[Pk[Long]] {
def reads(json: JsValue) = json match {
case l: JsNumber => JsSuccess(Id(l.value.toLong))
case _ => JsSuccess(NotAssigned)
}
}
implicit val AddressWrites: Writes[Address] = (
(JsPath \ "id").write[Pk[Long]] and
(JsPath \ "userId").write[Long] and
(JsPath \ "city").write[String]
)(unlift(Address.unapply))
implicit val AddressReads: Reads[Address] = (
(JsPath \ "id").read[Pk[Long]] and
(JsPath \ "userId").read[Long] and
(JsPath \ "city").read[String]
)(Address.apply _)
implicit val UserWrites: Writes[User] = (
(JsPath \ "id").write[Pk[Long]] and
(JsPath \ "name").write[String] and
(JsPath \ "email").write[String] and
(JsPath \ "addresses").write[List[Address]]
)(unlift(User.unapply))
def makeJson() = Action {
val johnAddr1 = Address(Id(1001), 1, "Chicago")
val johnAddr2 = Address(Id(1002), 1, "New York")
val janeAddr1 = Address(Id(1012), 1, "Dallas")
val john = User(Id(1), "John Doe", "john@email.com", List(johnAddr1, johnAddr2))
val jane = User(Id(2), "Jane Doe", "jane@email.com", List(janeAddr1))
Ok(Json.toJson(List(john, jane)))
// Ok(Json.toJson(map))
}