android - 从共享首选项获取时,GSON 将先前存储的 List 转换为 LinkedTreeMaps 的 ArrayList
问题描述
我希望能够使用 GSON 存储和获取对象的序列化列表。
但是,当我尝试获取列表时,我得到了 LinkedTreeMaps 的 ArrayList 的奇怪结构(每个对象属性)
这是我将某些内容存储到首选项存储的方法:
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()
}
我做错了什么?
解决方案
用于泛型序列化的 TypeToken
对于集合(和其他泛型)类型,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 in 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
- https://stackoverflow.com/a/44303909/2957169
推荐阅读
- msbuild - Azure DevOps - 将 MSBuild 属性作为参数传递给其他构建任务
- javascript - 通过 JS 获取倒数第二个 HTML 元素
- r - 根据因子条件在 R 中插入行
- sqlite - 如何在 initstate 中访问未来值?
- python - python pandas - 获取两个数据帧之间的匹配和不匹配记录
- python - Tensorflow 序列到 LSTM 序列
- python - 如果是的话,将关系数据库表存储为弹性搜索中的不同索引是否很好,那么如何在索引中传递关系
- javascript - 如何获取将 servlet 返回到 ajax 的特定字段?
- iframe - Youtube 嵌入显示不需要的顶部栏,即使 showinfo=0
- c - 关于 C 函数