У меня есть класс, который я пытаюсь десериализовать, используя функциональность json4s CustomSerializer
. Мне нужно сделать это из-за неспособности json4s десериализовать изменяемые коллекции.
Это базовая структура класса, который я хочу десериализовать (не беспокойтесь о том, почему класс устроен именно так):
case class FeatureValue(timestamp:Double)
object FeatureValue{
implicit def ordering[F <: FeatureValue] = new Ordering[F] {
override def compare(a: F, b: F): Int = {
a.timestamp.compareTo(b.timestamp)
}
}
}
class Point {
val features = new HashMap[String, SortedSet[FeatureValue]]
def add(name:String, value:FeatureValue):Unit = {
val oldValue:SortedSet[FeatureValue] = features.getOrElseUpdate(name, SortedSet[FeatureValue]())
oldValue += value
}
}
Json4s сериализует это просто отлично. Сериализованный экземпляр может выглядеть следующим образом:
{"features":
{
"CODE0":[{"timestamp":4.8828914447482E8}],
"CODE1":[{"timestamp":4.8828914541333E8}],
"CODE2":[{"timestamp":4.8828915127325E8},{"timestamp":4.8828910097466E8}]
}
}
Я пытался написать собственный десериализатор, но я не знаю, как работать с хвостами списка. В обычном сопоставителе вы можете просто рекурсивно вызвать свою собственную функцию, но в этом случае функция анонимна и вызывается через API json4s. Я не могу найти никаких примеров, которые касаются этого, и я не могу понять это.
В настоящее время я могу сопоставить только один хэш-ключ и один экземпляр FeatureValue
в его значении. Вот CustomSerializer в его нынешнем виде:
import org.json4s.{FieldSerializer, DefaultFormats, Extraction, CustomSerializer}
import org.json4s.JsonAST._
class PointSerializer extends CustomSerializer[Point](format => (
{
case JObject(JField("features", JObject(Nil)) :: Nil) => new Point
case JObject(List(("features", JObject(List(
(feature:String, JArray(List(JObject(List(("timestamp",JDouble(ts)))))))))
))) => {
val point = new Point
point.add(feature, FeatureValue(ts))
point
}
},
{
// don't need to customize this, it works fine
case x: Point => Extraction.decompose(x)(DefaultFormats + FieldSerializer[Point]())
}
))
Если я попытаюсь перейти на использование формата разделенного списка ::, до сих пор я получал ошибки компилятора. Даже если бы я не получил ошибок компилятора, я не уверен, что бы я с ними делал.