Как мне разобрать универсальный параметр класса из JSON в Scala?
У меня есть общая черта добытчика
trait Getter[A] {
def get: A
}
и я хотел бы разобрать JSON в список объектов, реализующих эту черту. Две такие реализации:
case class CoalesceGetter[A](getters: List[Getter[String]]) extends Getter[A] {
override def get: A = getters.map(_.get).find(_ != null).orNull
}
case class AsnGetter(ipGetter: Getter[String]) extends Getter[Long] {
override def get: Long = 99L // dummy function
}
Я хотел бы разобрать JSON в правильное Getter
класс, основанный на свойстве под названием function
что соответствует классу и type
который соответствует универсальному типу в случае геттеров, которые нуждаются в универсальном (оба свойства являются строками в BLOB-объекте json, который я анализирую). Я смотрел на нестандартные сериализаторы для json4s, но не понимаю, как работать с дженериками. Любая помощь приветствуется!
1 ответ
Прежде всего, я не думаю, что это хорошая идея - jsonify классов с аргументом типа. Я думаю, что это лучший дизайн, чтобы определить нетипизированные (case) классы, которые являются прямым эквивалентом вашего объекта json, и использовать стандартное чтение / запись json, как предусмотрено многими библиотеками.
Но затем, чтобы ответить на ваш вопрос, я хотел бы ответить еще на один вопрос: как бы вы сделали это "вручную"? Т.е. как бы вы писали и читали разные CoalesceGetter[A] с разными A?
Вот предложение: поместите тип arg в поле json:
"ofInt": {"type-arg":"Int", "getters":[ ... list of getters in json ...]},
"ofDouble":{"type-arg":"Double", "getters":[ ... list of getters in json ...]}
Теперь, если вы напишите читателю, как вы будете создавать экземпляры 2 ofInt и ofDouble, зная аргументы типа "Int" и "Double" (которые являются строковыми!).
Я вижу 2 решения:
1) Либо у вас есть жестко закодированная карта типа arg-type => фактический тип scala
argType match{
case "Int" => new CoalesceGetter[Int](...)
case "Double" => new CoalesceGetter[Double](...)
}
2) Или вы сохраняете и считываете обобщенный тип как строковое значение в строке типа arg, например java Class.forName (см., Например, [ /questions/30881688/java-kak-sozdat-ekzemplyar-klassa-iz-stroki/30881701#30881701). Но это действительно очень плохая идея ИМХО.
(примечание: если вы хотите сериализовать какой-либо объект только для того, чтобы позже перезагрузить его или на другом компьютере, не используйте json, а используйте специальную сериализацию, такую как Java Serialization или kryo, которую использует spark)