当从共享prefs获取时,GSON将先前存储的List转换为LinkedTreeMaps的ArrayList

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当从共享prefs获取时,GSON将先前存储的List转换为LinkedTreeMaps的ArrayList相关的知识,希望对你有一定的参考价值。

我希望能够使用GSON存储和获取序列化的对象列表。

但是,当我试图获取List时,我得到了LinkedTreeMaps的ArrayList的奇怪结构(每个对象属性)

这是我存储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()
  }

我做错了什么?

答案

TypeTokens for Generic-Type Serialization

对于集合(和其他通用)类型,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)

如果你想保持内部类型的通用性,即List<T>中的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

以上是关于当从共享prefs获取时,GSON将先前存储的List转换为LinkedTreeMaps的ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

SharedPreferences会在使用前不断删除

GSON可能出现故障?还是编码不好?

If-else语句基于先前的活动选择来获取共享偏好

如何在HashMap中存储一个带Gson的JSON

如何在 Kotlin 中将 TypeToken + 泛型与 Gson 一起使用

如何将 java.util.prefs.Preferences 存储在文件中?