У меня есть иерархия классов, представляющая типы фильтров, и один из типов содержит список базовых типов. Я не могу понять, как настроить форматы spray-json для этих типов, потому что средства форматирования для базового типа и содержащего типа должны ссылаться друг на друга.
Начнем с иерархии классов и форматов json, где проблемные части закомментированы:
object Filters {
sealed trait Filter
case class SimpleFilter(foo: String) extends Filter
case class DoubleFilter(foo: String, bar: String) extends Filter
implicit val simpleFormat = jsonFormat1(SimpleFilter)
implicit val doubleFormat = jsonFormat2(DoubleFilter)
// case class AndFilter(filters: List[Filter]) extends Filter
// implicit val andFormat = lazyFormat(jsonFormat1(AndFilter))
// (would really use a type field, keeping simple for example)
implicit val filterFormat = new RootJsonFormat[Filter] {
override def write(obj: Filter): JsValue = obj match {
case x: SimpleFilter => x.toJson
case x: DoubleFilter => x.toJson
// case x: AndFilter => x.toJson
}
override def read(json: JsValue): Filter = json.asJsObject.getFields("bar") match {
case Seq(_) => json.convertTo[DoubleFilter]
case Seq() => json.convertTo[SimpleFilter]
}
}
}
Это компилируется и работает так, как ожидалось, я могу сериализовать и десериализовать конкретные подклассы фильтров как Filter без проблем.
Но давайте прокомментируем AndFilter
материал. Теперь беда! Если объявление andFormat
перед filterFormat
(как указано выше), оно не будет компилироваться, потому что andFormat
требуется filterFormat
:
Ошибка: (17, 43) не удалось найти неявное значение для параметра свидетельства типа spray.json.DefaultJsonProtocol.JF [List [classpath.Filters.Filter]] implicit val andFormat = jsonFormat1 (AndFilter)
Изменение порядка на andFormat
после filterFormat
позволит компилировать вещи. Но, конечно, я также хочу добавить andFormat
ссылки на формат filter
, то есть case x: AndFilter => x.toJson
в методе записи и все, что включает json.convertTo[AndFilter]
в методе чтения. И это тоже не компилируется:
Ошибка: (23, 34) Не удается найти класс типа JsonWriter или JsonFormat для classpath.Filters.Filter с classpath.Filters.AndFilter case x: AndFilter => x.toJson
Я не могу найти способ обойти это. Я пробовал использовать метод spray-json lazyFormat
, но это не помогает (работает только для рекурсивных ссылок на себя, а не для таких перекрестных ссылок). Любые идеи?