Мне нужно десериализовать ответ JSON, в котором одно из полей может быть установлено для разных объектов (только с одним общим полем). Реальная модель довольно сложна, но, например, мы можем представить ее двумя классами case, расширяющими seled trait:
sealed trait Item {
val itemType: String
}
case class FirstItem(
itemType: String = "FirstItem",
firstProperties: SomeComplexType
) extends Item
case class SecondItem(
itemType: String = "SecondItem",
secondProperties: SomeOtherComplexType,
secondName: String,
secondSize: Int
) extends Item
Поскольку Json4s не знает, как обрабатывать этот объект, я написал собственный сериализатор:
object ItemSerializer extends CustomSerializer[Item](_ => ({
case i: JObject =>
implicit val formats: Formats = DefaultFormats
(i \ "itemType").extract[String] match {
case "FirstType" => i.extract[FirstItem]
case "SecondItem" => i.extract[SecondItem]
}
}, {
case x: Item => x match {
case f: FirstItem => JObject() //TODO
case s: SecondItem => JObject() //TODO
}
}))
Первая часть - десериализация не идеальна, так как сильно зависит от поля типа, но она подходит для моих нужд. Проблема во второй части - сериализации. В примерах я обнаружил, что люди обычно записывают каждое поле шаг за шагом, но обычно они сериализуют некоторые простые объекты. В моем случае этот объект имеет несколько уровней и в общей сложности более 60-80 полей, поэтому это приведет к довольно грязному и трудному для чтения коду. Поэтому мне интересно, есть ли лучший способ сделать это, поскольку и FirstItem
, и SecondItem
можно десериализовать, используя только DefaultFormats
. Есть ли способ сообщить Json4s, что если объект соответствует заданному типу, он должен быть сериализован с форматом по умолчанию?