У меня возникла проблема с сериализацией модели: Моя модель:
case class DocumentModel(
documentId: Option[Int] = None,
title: String,
...
responsibleList: Option[Seq[UserModel]], // No problem
preConditions: Option[Seq[Object]], // Problem occurs here
postConditions: Option[Seq[Object]] // Problem occurs here
)
object DocumentModel {
implicit val documentFormat = Jsonx.formatCaseClass[DocumentModel]
}
responsibleList
, preConditions
, а также postConditions
не хранятся в базе данных, они служат только в качестве вспомогательных списков. Я продолжаю заполнять эти списки в своем контроллере, чтобы отправить его обратно во внешний интерфейс через JSON
:
val document = for {
newDocument <- documentDTO.getDocument(documentId, clientId)
responsibleList <- raciDocumentDTO.getResponsible_Documents(documentId)
...
preConditions <- conditionController.getPreConditions(documentId)
postConditions <- conditionController.getPostConditions(documentId)
} yield (newDocument, responsibleList, ..., preConditions, postConditions)
document.map({ case (newDocument, responsibleList, ..., preConditions, postConditions) =>
val temp = newDocument.map(docu => {
...
val doc = new DocumentModel(
docu.documentId,
docu.title,
...
Some(responsibleList),
Some(preConditions),
Some(postConditions)
)
doc
})
Ok(Json.obj(
"document" -> temp,
))
})
Я подозреваю, что это как-то связано с Option[Seq[Object]]
или Option[Seq[Any]]
в этом отношении. Компилятор выдает ошибку:
Поскольку preConditions
и postConditions
могут быть instances/objects
из различных models
, я не могу явно указать, какой это должна быть модель. Есть ли решение этой проблемы или мне нужно идти другим путем?
Заранее спасибо!
ОБНОВИТЬ
Я добавил:
trait Condition
object Condition {
import play.api.libs.json._
implicit val conditionWrites: Writes[Condition] = Writes[Condition] {
case a: DocumentModel => JsObject(Seq("DocumentModel" -> Jsonx(a)))
case b: ProcessModel => JsObject(Seq("ProcessModel" -> Jsonx(b)))
case c: ProcessInstanceModel => JsObject(Seq("ProcessInstanceModel" -> Jsonx(c)))
}
}
А в моих моделях:
case class DocumentModel(
documentId: Option[Int] = None,
title: String,
...,
responsibleList: Option[Seq[UserModel]],
preConditions: Option[Seq[Condition]],
postConditions: Option[Seq[Condition]]
) extends Condition
Это все еще оставляет мне это сообщение об ошибке:
Я впервые столкнулся с такой проблемой и, честно говоря, немного запутался.
Обновление 2
Я пробовал, как вы упомянули, но все равно вызывает ту же ошибку.
Мой код выглядит так:
ОБНОВИТЬ
Я реализовал предложенные изменения и сузил проблему до следующего:
trait Condition
object Condition {
implicit val conditionWrites: Writes[Condition] = Writes[Condition] {
case a: DocumentModel => JsObject(Seq(
"documentId" -> Json.toJson(a.documentId),
"title" -> Json.toJson(a.title),
...
"responsibleList" -> Json.toJson(a.responsibleList),
"preConditions" -> Json.toJson(a.preConditions),
"postConditions" -> Json.toJson(a.postConditions)
))
case b: ...
}
}
Когда я делаю это так, я получаю следующее сообщение об ошибке:
Итак, я подумал, что implicit read
может отсутствовать. Итак, я добавил:
object Condition {
implicit val conditionReads: OFormat[Condition] = Json.format[Condition] // New
implicit val conditionWrites: Writes[Condition] = Writes[Condition] {
case a: DocumentModel => JsObject(Seq(
"documentId" -> Json.toJson(a.documentId),
"title" -> Json.toJson(a.title),
...
Однако при запуске кода я получаю следующее:
No unapply or unapplySeq function found
[error] implicit val conditionReads: OFormat[Condition] = Json.format[Condition]
Предлагаемое решение для исправления этого состояло в том, чтобы заменить мой object condition
на case class condition
. Однако это разрушило бы всю цель создания такого универсального trait/object
.
Сделайте так, чтобы все ваши "условные" модели расширяли черту, имеющую возможность записи в JSON. Например,
trait Condition
object Condition {
implicit val conditionWrites: Writes[Condition] = Writes[Condition] {
case a: PreConditionA => JsObject(Seq("field" -> JsString(a.stringValue))) //or whatever
case b: PreConditionB => //...
//etc...
case x: PostConditionX => //...
case y: PostConditionY => //...
//etc...
}
}
case class PreConditionA(stringValue: String) extends Condition
//etc.
Затем в DocumentModel
измените типы условий на признак Condition
:
case class DocumentModel(
documentId: Option[Int] = None,
title: String,
//...
responsibleList: Option[Seq[UserModel]],
preConditions: Option[Seq[Condition]],
postConditions: Option[Seq[Condition]]
)
Возможно, вам придется преобразовать синтаксис сериализации к тому, что он есть для Jsonx, но, надеюсь, он достаточно похож, и вы поняли идею.