У меня есть следующая иерархия классов:
object Calendar {
trait DayType
case object Weekday extends DayType
case object Weekend extends DayType
case object Holiday extends DayType
}
trait Calendar {
def dateType(date: LocalDate): Calendar.DayType
}
class ConstantCalendar(dayType: Calendar.DayType) extends Calendar {
override def dateType(date: LocalDate) = dayType
}
case object DefaultCalendar extends ConstantCalendar(Calendar.Weekday)
case class WeekdaysCalendar(defaults: Array[Calendar.DayType]) extends Calendar {
override def dateType(date: LocalDate) = defaults(date.getDayOfWeek - 1)
}
case class CustomCalendar(defaultCalendar: Calendar = DefaultCalendar,
dates: Map[LocalDate, Calendar.DayType] = Map.empty)
extends Calendar {
private def defaultType(date: LocalDate) = defaultCalendar.dateType(date)
private val dateMap = dates.withDefault(defaultType)
override def dateType(date: LocalDate) = dateMap(date)
}
Я определил следующие сериализаторы:
class JsonFormats(domainTypeHints: TypeHints,
domainCustomSerializers: List[Serializer[_]] = Nil,
domainFieldSerializers: List[(Class[_], FieldSerializer[_])] = Nil)
extends DefaultFormats {
override val typeHintFieldName = "type"
override val typeHints = domainTypeHints
override val customSerializers = JodaTimeSerializers.all ++ domainCustomSerializers
override val fieldSerializers = domainFieldSerializers
}
class JsonCalendarSerializer extends CustomSerializer[CustomCalendar]( format => (
{
case JObject(JField("type", JString("CustomCalendar")) ::
JField("defaultCalendar", JString(defaultCalendar)) ::
JField("dates", dates) ::
Nil
) =>
CustomCalendar(defaultCalendar) // TODO dates
},
{
case cal: CustomCalendar =>
val dates = cal.dates.foldLeft(JObject()) { (memo, dt) =>
dt match {
case (d, t) => memo ~ (f"${d.getYear}%04d-${d.getMonthOfYear}%02d-${d.getDayOfMonth}%02d", t.toString)
}
}
("type" -> "CustomCalendar") ~
("defaultCalendar" -> cal.defaultCalendar) ~
("dates" -> dates)
}
))
implicit val jsonFormats = new JsonFormats(ShortTypeHints(List(Calendar.Weekday.getClass,
Calendar.Weekend.getClass,
Calendar.Holiday.getClass,
classOf[CustomCalendar])),
new JsonCalendarSerializer :: Nil)
Мне пришлось создать собственный сериализатор, чтобы обойти тот факт, что в Json4 ключи карты должны быть строками.
У меня есть файл, который может содержать данные для какого-то календаря, но я заранее не знаю, какой это тип календаря.
Когда я пытаюсь сделать следующее:
val cal = CustomCalendar("default", Map(new LocalDate(2013, 1, 1) -> Calendar.Holiday))
val ser = Serialization.write(cal)
val cal2: Calendar = Serialization.read(ser)
Я получил:
org.json4s.package$MappingException: Do not know how to deserialize 'CustomCalendar'
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$mkWithTypeHint(Extraction.scala:444)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$6.apply(Extraction.scala:452)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$6.apply(Extraction.scala:450)
at org.json4s.Extraction$.org$json4s$Extraction$$customOrElse(Extraction.scala:462)
at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:450)
at org.json4s.Extraction$.extract(Extraction.scala:306)
at org.json4s.Extraction$.extract(Extraction.scala:42)
at org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21)
at org.json4s.jackson.Serialization$.read(Serialization.scala:50)
Итак, кажется, что Json4s не может найти мой сериализатор.
Итак... есть намеки? Либо о том, как заставить Json4s сериализовать/десериализовать Карты с нестроковыми ключами, либо как заставить это работать?
Спасибо!