簡體   English   中英

Play Framework 2.3 Scala-使用隱式Writes轉換器將嵌套對象序列化為JSon

[英]Play Framework 2.3 Scala - Serialize nested objects to JSon with implicit Writes converters

我需要一個前端jquery-component一個像這樣的特定json對象(ajax響應):

[
    {"division":"IT", "contacts":[
        {“firstname”:”Carl”, “surname”:”Smith”, “empID”:1},
        {“firstname”:”Henry”, “surname”:”Miller”, “empID”:2}
]}, 
    {"division":"Sales", "contacts":[
        {“firstname”:”Nancy”, “surname”:”McDonald”, “empID”:3},
        {“firstname”:”Susan”, “surname”:”McBright”, “empID”:4}
]}
]

在后端中,數據是通過anorm(MySQL)讀取的,並轉換為以下對象:

List(Map("division" -> "IT", "contacts" -> List(c3,c4)), Map("division" -> "Sales",          "contacts" -> List(c3,c4)))

然后,我嘗試將Object序列化為JSon,但沒有成功(包括隱式Writes轉換器)。 下面,我以相同的方式制作了一個簡化的測試用例Idea-Worksheet:

import play.api.libs.json.{JsValue, Json, Writes}

case class Contact(firstname: String, surname: String, empID: Option[Int])

case class ContactDivisionList(division: String, contacts: Seq[Contact])

implicit val ctWrites = new Writes[Contact] {
  def writes(ct: Contact) = Json.obj(
    "firstname" -> ct.firstname,
    "surname" -> ct.surname,
    "empid" -> ct.empID
  )
}

implicit val sdlWrites = new Writes[ContactDivisionList] {
  def writes(dlist: ContactDivisionList) = Json.obj(
    "division" -> dlist.division,
    "contacts" -> Json.toJson(dlist.contacts)
  )
}


/*
Example
*/
val c1 = Contact("Carl","Smith",Option(1))
val c2 = Contact("Henry","Miller",Option(2))
val c3 = Contact("Nancy","McDonald",Option(3))
val c4 = Contact("Susan","McBright",Option(4))

//Test case 1 ->OK
Json.toJson(List(c1,c2,c3,c4))

//Test case 2 ->OK
val c_comp1=List(Map("contacts" -> List(c1,c2)),Map("contacts" -> List(c3,c4)))
//RESULT --> c_comp1: List[scala.collection.immutable.Map[String,List[Contact]]] =     List(Map(contacts -> List(Contact(Carl,Smith,Some(1)), Contact(Henry,Miller,Some(2)))),   Map(contacts -> List(Contact(Nancy,McDonald,Some(3)), Contact(Susan,McBright,Some(4)))))
Json.toJson(c_comp1)
//res1: play.api.libs.json.JsValue = [{"contacts":    [{"firstname":"Carl","surname":"Smith","empid":1},{"firstname":"Henry","surname":"Miller","empid":2}]},{"contacts":[{"firstname":"Nancy","surname":"McDonald","empid":3},{"firstname":"Susan","surname":"McBright","empid":4}]}]


//Test case 3 ->Fail!!!
val c_comp2 = List(Map("division" -> "IT", "contacts" -> List(c1,c2)),Map("division" ->  "Sales", "contacts" -> List(c3,c4)))
//sdlWrites: play.api.libs.json.Writes[ContactDivisionList]{def writes(dlist:    ContactDivisionList): play.api.libs.json.JsObject} = $anon$2@3738baec

Json.toJson(c_comp2)
//!!!!!Error messages
/*Error:(39, 13) No Json serializer found for type     List[scala.collection.immutable.Map[String,java.io.Serializable]]. Try to implement an    implicit Writes or Format for this type.
Json.toJson(c_comp2)
^

Error:(39, 13) not enough arguments for method toJson: (implicit tjs:    play.api.libs.json.Writes[List[scala.collection.immutable.Map[String,java.io.Serializable]]    ])play.api.libs.json.JsValue.
Unspecified value parameter tjs.
Json.toJson(c_comp2)
^
*/

在腳本的結尾,您可以看到“測試案例3”,當我執行Json.toJson(c_comp2)時出現錯誤->“未找到類型的Json序列化器。”。 我嘗試了很多事情,但我做得不好。 成功完成“測試用例2”的唯一區別是,我使用String-Tuppel擴展了Map。

我希望有人可以幫助我解決這個問題,Thx

最好的問候卡斯滕

您的問題是您那里的MapString映射到String (您的部門名稱)和List[Contact]的最小上限,后者恰好是java.io.Serializable

scala> case class Contact(firstname: String, surname: String, empID: Option[Int])
defined class Contact

scala> case class ContactDivisionList(division: String, contacts: Seq[Contact])
defined class ContactDivisionList

scala> val c1 = Contact("Carl","Smith",Option(1))
c1: Contact = Contact(Carl,Smith,Some(1))

scala> val c2 = Contact("Henry","Miller",Option(2))
c2: Contact = Contact(Henry,Miller,Some(2))

scala> val c3 = Contact("Nancy","McDonald",Option(3))
c3: Contact = Contact(Nancy,McDonald,Some(3))

scala> val c4 = Contact("Susan","McBright",Option(4))
c4: Contact = Contact(Susan,McBright,Some(4))

scala> Map("division" -> "IT", "contacts" -> List(c1,c2))
res10: scala.collection.immutable.Map[String,java.io.Serializable] = Map(division -> IT, contacts -> List(Contact(Carl,Smith,Some(1)), Contact(Henry,Miller,Some(2))))

我不確定您問題的性質,但是如果您已經有了List[ContactDivisionList] ,將其序列化為JSON很簡單:

scala> implicit val contactWrites = Json.writes[Contact]
contactWrites: play.api.libs.json.OWrites[Contact] = play.api.libs.json.OWrites$$anon$2@3676af92

scala> implicit val contactDivisionListWrites = Json.writes[ContactDivisionList]
contactDivisionListWrites: play.api.libs.json.OWrites[ContactDivisionList] = play.api.libs.json.OWrites$$anon$2@2999d17d

scala> Json.toJson(List(ContactDivisionList("IT", List(c1,c2)), ContactDivisionList("Sales", List(c3, c4))))
res2: play.api.libs.json.JsValue = [{"division":"IT","contacts":[{"firstname":"Carl","surname":"Smith","empID":1},{"firstname":"Henry","surname":"Miller","empID":2}]},{"division":"Sales","contacts":[{"firstname":"Nancy","surname":"McDonald","empID":3},{"firstname":"Susan","surname":"McBright","empID":4}]}]

在我看來,您應該首先避免使用該Map 我以前從未使用過anorm,但是我認為您需要查看的是數據結構的代碼,因為到那時,您已經失去了類型安全性。 理想情況下,您應該使用ContactDivisionList或直接使用JsValue案例構造對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM