Я хочу иметь возможность хранить и получать сериализованный список объектов с помощью GSON.
Однако, когда я пытаюсь получить список, я получаю странную структуру ArrayList из LinkedTreeMaps (каждый для свойства объекта)
Вот мой способ сохранить что-то в хранилище prefs:
fun <T> putAsJson(key: String, valueObject: T?) {
if (valueObject != null) {
put(key, gson.toJson(valueObject))
} else {
put(key, null)
}
}
И вот как я получаю это:
inline fun <reified T: Any> getFromJson(key: String): T? {
val jsonValue = get<String>(key)
return try {
gson.fromJson(jsonValue, T::class.java)
} catch (ex: Exception) {
Timber.e(ex, "Error when parsing JSON representing ${T::class.java} class")
null
}
}
Так что я просто храню это как:
fun saveSomeList(list: List<SomeObject>?) {
someStorage.putAsJson(KEY, list)
}
И тогда я пытаюсь получить его, используя этот метод:
fun getSomeList(): List<SomeObject> {
return someStorage.getFromJson<List<SomeObject>>(KEY) ?: emptyList()
}
Что я делаю не так?
Для коллекционных (и других универсальных) типов GSON не может автоматически извлечь правильный тип. Вам нужно помочь, предоставив "токен типа":
// Known list
val ints = listOf(1, 2, 3)
val collectionType = object : TypeToken<Collection<Int>>() {}.type
val json = gson.toJson(ints, collectionType)
val ints2: List<Int> = gson.fromJson(json, collectionType)
// Known generic
val foo = Foo<Bar>()
val fooType = object : TypeToken<Foo<Bar>>() {}.type
val json = gson.toJson(foo, fooType)
val foo2: Foo<Bar> = gson.fromJson(json, fooType)
Если вы хотите сохранить универсальность вашего внутреннего типа, то есть T в List<T>
, вы можете сделать это:
// Unknown generic
val modelType = T::class.java
val listType = TypeToken.getParameterized(List::class.java, modelType).type
val list = gson.fromJson(jsonValue, listType)
Я думаю, что ваш лучший вариант - это особый метод для списков:
inline fun <reified T: Any> getListFromJson(key: String): T? {
val jsonValue = get<String>(key)
return try {
val listType = TypeToken.getParameterized(List::class.java, T::class.java).type
gson.fromJson(jsonValue, listType)
} catch (ex: Exception) {
Timber.e(ex, "Error when parsing JSON representing List<${T::class.java}> class")
null
}
}
Источники:
- https://github.com/google/gson/blob/master/UserGuide.md#TOC-Collections-Examples
- qaru.site/questions/130638/...