2

User と Address の 2 つのクラスがあります。

case class User(
  id: Pk[Long] = NotAssigned,
  name: String = "",
  email: String = "",
  addresses: Seq[Address])

case class Address(
  id: Pk[Long] = NotAssigned,
  userId: Long,
  city: String)

私のコントローラーから、すべてのユーザーをアドレスとともに送信する必要がありますMap[User, List[Address]]。anorm (mysql) を使用してそれらを抽出できましたが、json として送信する必要があります。上記の書き込みと読み取りを実装する方法を教えてくださいMap[User, List[Address]]。ありがとうございます。

4

3 に答える 3

5

それは役立つはずです

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


case class User(
  id: Pk[Long] = NotAssigned,
  name: String = "",
  email: String = "",
  addresses: Seq[Address])

case class Address(
  id: Pk[Long] = NotAssigned,
  userId: Long,
  city: String)

// Play does not provide Format[Pk[A]], so you need to define it
implicit def pkReads[A](implicit r: Reads[Option[A]]): Reads[Pk[A]] = r.map {  _.map(Id(_)).getOrElse(NotAssigned)  }
implicit def pkWrites[A](implicit w: Writes[Option[A]]): Writes[Pk[A]] =  Writes(id => w.writes(id.toOption))

implicit val addrFormat = Json.format[Address]
implicit val userFormat = Json.format[User]

ユーザーを簡単にシリアル化できるようになりました。

val as = Seq(Address(Id(2), 1, "biim"))
val u = User(Id(1), "jto", "jto@foo.bar", as)

scala> Json.toJson(u)
res6: play.api.libs.json.JsValue = {"id":1,"name":"jto","email":"jto@foo.bar","addresses":[{"id":2,"userId":1,"city":"biim"}]}

ジュリアンが言うように、単にシリアライズすることはできませんMap[User, Seq[Address]]。User は Json オブジェクトのキーになれないため、意味がありません。

于 2013-08-02T09:44:37.043 に答える
4

Map[User, List[Address]]を に変換することでこの問題を解決できList[User]、JsonWriter が書きやすくなります。

何かのようなもの:

list.map {
  case (user, address) => user.copy(addresses = address.toSeq)
}
于 2013-07-29T08:31:57.407 に答える
2

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))
  }
于 2013-08-04T15:31:20.310 に答える