Проблема немного скрыта тем, что вы не регистрируете исключение перед возвратом пустого списка. Если вы зарегистрируете это исключение, вы получите это:
java.lang.RuntimeException: не удалось вызвать закрытый arrow.core.Option () без аргументов
Это означает, что Gson не знает, как создать класс Option
, потому что у него нет открытого пустого конструктора. Действительно, Option
- это запечатанный класс (, следовательно, абстрактный ), имеющий 2 конкретных дочерних класса: Some
и None
. Чтобы получить экземпляр Option
, вы должны использовать один из фабричных методов, например, Option.just(xxx)
или Option.empty()
.
Теперь, чтобы исправить ваш код, вы должны сказать Gson, как десериализовать класс Option
. Для этого вам нужно зарегистрировать адаптер типа для вашего объекта gson
.
Возможная реализация:
class OptionTypeAdapter<E>(private val adapter: TypeAdapter<E>) : TypeAdapter<Option<E>>() {
@Throws(IOException::class)
override fun write(out: JsonWriter, value: Option<E>) {
when (value) {
is Some -> adapter.write(out, value.t)
is None -> out.nullValue()
}
}
@Throws(IOException::class)
override fun read(input: JsonReader): Option<E> {
val peek = input.peek()
return if (peek != JsonToken.NULL) {
Option.just(adapter.read(input))
} else {
input.nextNull()
Option.empty()
}
}
companion object {
fun getFactory() = object : TypeAdapterFactory {
override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
val rawType = type.rawType as Class<*>
if (rawType != Option::class.java) {
return null
}
val parameterizedType = type.type as ParameterizedType
val actualType = parameterizedType.actualTypeArguments[0]
val adapter = gson.getAdapter(TypeToken.get(actualType))
return OptionTypeAdapter(adapter) as TypeAdapter<T>
}
}
}
}
Вы можете использовать его следующим образом:
fun main(args: Array<String>) {
val gson = GsonBuilder()
.registerTypeAdapterFactory(OptionTypeAdapter.getFactory())
.create()
val result: List<Book> = try {
gson.fromJson(json, TypeToken.getParameterized(List::class.java, Book::class.java).type)
} catch (e: Exception) {
e.printStackTrace()
emptyList()
}
println(result)
}
Этот код выводит:
[Book(title=Book100, author=Author100, borrower=Some(Borrower(name=Borrower100, maxBooks=100))), Book(title=Book200, author=Author200, borrower=None)]