【问题标题】:Serializing class with multiple generics using GSON使用 GSON 序列化具有多个泛型的类
【发布时间】:2018-12-03 15:49:19
【问题描述】:

我有一个包含两个泛型列表的数据类:

data class Warehouse(
    val cars: MutableList<out Car>,
    val planes: MutableList<out Plane>,
)

目前,我尝试使用以下方法序列化我的对象:

val warehouse = Warehouse(cars, planes)
val json = Gson().toJson(warehouse)

这给了我以下 json:

{
    "cars": [
    {}
  ],
    "planes": [
    {}
  ],
}

如果我使用

序列化汽车
val cars: MutableList<Car> = getCars()
val json = Gson().toJson(cars)

一切都按预期工作,即 json 包含正确的信息。

根据文档,已知类型的对象可以包含任何泛型类型的字段:

 /**
   * This method serializes the specified object into its equivalent Json representation.
   * This method should be used when the specified object is not a generic type. This method uses
   * {@link Class#getClass()} to get the type for the specified object, but the
   * {@code getClass()} loses the generic type information because of the Type Erasure feature
   * of Java. Note that this method works fine if the any of the object fields are of generic type,
   * just the object itself should not be of a generic type. If the object is of generic type, use
   * {@link #toJson(Object, Type)} instead. If you want to write out the object to a
   * {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
   *
   * @param src the object for which Json representation is to be created setting for Gson
   * @return Json representation of {@code src}.
   */

我在这里错过了什么?

【问题讨论】:

标签: android serialization gson


【解决方案1】:

解决办法是手动注册不同类型的适配器:

val json = GsonBuilder()
            .registerTypeAdapter(Car::class.java, CarSerializer())
            .registerTypeAdapter(Plane::class.java, PlaneSerializer())
            .create()
            .toJson(data)

CarSerializer 定义为:

class CarSerializer : JsonSerializer<Car> {

    override fun serialize(src: Car, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
        return when (src) {
            is Ferrari -> context.serialize(src, Ferrari::class.java)
            is Mercedes -> context.serialize(src, Mercedes::class.java)
            else -> throw IllegalArgumentException("Unspecified class serializer for ${src.javaClass.name}")
        }
    }
}

PlaneSerializer 的定义方式相同。

【讨论】:

    猜你喜欢
    • 2015-05-03
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多