[英]Play2 Scala: Deserialize Json into a List of objects
我正在嘗試將使用 Play 的WSClient
獲得的 json 正文響應反序列化為對象列表,我認為我離成功還不算太近,但可能還有最后一塊拼圖缺少我。
這些是傳入 json 必須反序列化為的 case 類(及其伴隨對象)。
EmployerStoreDTO:
import play.api.libs.json._
case class EmployerStoreDTO (id: String, storeName: String)
object EmployerStoreDTO {
implicit val reads: Reads[EmployerStoreDTO] = Json.reads[EmployerStoreDTO]
implicit val employerStoreDTOlistReads: Reads[List[EmployerStoreDTO]] = Reads.list[EmployerStoreDTO]
}
公司雇主DTO:
import java.time.DayOfWeek
import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.functional.syntax._
case class CompanyEmployerDTO(id: String,
companyName: String,
companyUrl: Option[String],
description: Option[String],
startDayOfWeek: DayOfWeek,
logoUrl: Option[String],
stores: List[EmployerStoreDTO] = List(),
supportHelpText: Option[String],
themeId: Option[String]) {
}
object CompanyEmployerDTO {
import model.EmployerStoreDTO._
implicit val startDayOfWeekReads: Reads[DayOfWeek] = (JsPath \ "weekStartDay").read[Int].map(DayOfWeek.of)
implicit val reads: Reads[CompanyEmployerDTO] = (
(JsPath \ "id").read[String] and
(JsPath \ "companyName").read[String] and
(JsPath \ "companyUrl").readNullable[String] and
(JsPath \ "description").readNullable[String] and startDayOfWeekReads and
(JsPath \ "logoUrl").readNullable[String] and employerStoreDTOlistReads and
(JsPath \ "supportHelpText").readNullable[String] and
(JsPath \ "themeId").readNullable[String]
) (CompanyEmployerDTO.apply _)
implicit val companyEmployerDTOListReads: Reads[List[CompanyEmployerDTO]] = Reads.list[CompanyEmployerDTO]
}
CompanyEmployerCollectionDTO:
import play.api.libs.json.Reads._
import play.api.libs.json._
case class CompanyEmployerCollectionDTO (companies: List[CompanyEmployerDTO])
object CompanyEmployerCollectionDTO {
implicit val reads: Reads[CompanyEmployerCollectionDTO] =
(JsPath \ "companies").read[List[CompanyEmployerDTO]].map(CompanyEmployerCollectionDTO.apply)
}
但當我試圖反序列化響應如下: response.json.as[CompanyEmployerCollectionDTO]
我收到此錯誤:
Caused by: play.api.libs.json.JsResultException: JsResultException(errors:List((/companies(0),List(JsonValidationError(List(error.expected.jsarray),WrappedArray())))))
at play.api.libs.json.JsReadable.$anonfun$as$2(JsReadable.scala:25)
at play.api.libs.json.JsError.fold(JsResult.scala:64)
at play.api.libs.json.JsReadable.as(JsReadable.scala:24)
at play.api.libs.json.JsReadable.as$(JsReadable.scala:23)
at play.api.libs.json.JsObject.as(JsValue.scala:124)
at services.com.mycompany.ApiEmployeeClient.$anonfun$callGetEmployers$2(ApiEmployeeClient.scala:33)
at scala.util.Success.$anonfun$map$1(Try.scala:255)
at scala.util.Success.map(Try.scala:213)
at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)
at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)
問題是裸露and employerStoreDTOlistReads
。 由於您尚未指定路徑(對於其他CompanyEmployerDTO
成員),解碼器將嘗試將當前 JSON 值本身(代表CompanyEmployerDTO
的對象)解碼為EmployerStoreDTO
列表。
用and (JsPath \\ "stores").read[List[EmployerStoreDTO]]
替換這兩個詞應該可以修復您的代碼,但是對於值得的,您還可以通過廢棄List
實例(將提供)來大大簡化您的實現自動),刪除導入等:
import play.api.libs.json._
case class EmployerStoreDTO (id: String, storeName: String)
object EmployerStoreDTO {
implicit val reads: Reads[EmployerStoreDTO] = Json.reads[EmployerStoreDTO]
}
import java.time.DayOfWeek
import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.functional.syntax._
case class CompanyEmployerDTO(id: String,
companyName: String,
companyUrl: Option[String],
description: Option[String],
startDayOfWeek: DayOfWeek,
logoUrl: Option[String],
stores: List[EmployerStoreDTO] = List(),
supportHelpText: Option[String],
themeId: Option[String]) {
}
object CompanyEmployerDTO {
implicit val reads: Reads[CompanyEmployerDTO] = (
(JsPath \ "id").read[String] and
(JsPath \ "companyName").read[String] and
(JsPath \ "companyUrl").readNullable[String] and
(JsPath \ "description").readNullable[String] and
(JsPath \ "weekStartDay").read[Int].map(DayOfWeek.of) and
(JsPath \ "logoUrl").readNullable[String] and
(JsPath \ "stores").read[List[EmployerStoreDTO]] and
(JsPath \ "supportHelpText").readNullable[String] and
(JsPath \ "themeId").readNullable[String]
) (CompanyEmployerDTO.apply _)
}
import play.api.libs.json.Reads._
import play.api.libs.json._
case class CompanyEmployerCollectionDTO (companies: List[CompanyEmployerDTO])
object CompanyEmployerCollectionDTO {
implicit val reads: Reads[CompanyEmployerCollectionDTO] =
(JsPath \ "companies").read[List[CompanyEmployerDTO]].map(CompanyEmployerCollectionDTO.apply)
}
這將與您的代碼做完全相同的事情,但更簡潔和易於管理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.