【问题标题】:how to build the Gson for creating different pojo classes based on the json string's data using gson.fromJson()如何使用 gson.fromJson() 基于 json 字符串数据构建 Gson 以创建不同的 pojo 类
【发布时间】:2019-04-02 23:48:09
【问题描述】:

当使用改造从远程获取 json 并解析为 pojo 时, 并且 json 在每个项目中都有“类型”,根据类型将创建不同的 pojo 类。

{
"result": [
    {
        "type": "stroy",
        "stroy_data_1": xxx,
        "story_data_2": yyy
    },
    {
        "type": "detail",
        "detail_data_1": 111,
        "detail_data_2": 222
    }
]
}

使用 retofit,它可以由 addConverterFactoryConverter.Factory 完成,例如: 这里使用RuntimeTypeAdapterFactory 构建一个dataAdapter 来创建Gson 并要求根据“类型”创建类

fun createCustomeDataGson(): Gson {
    val dataAdapter = RuntimeTypeAdapterFactory
            .of(TopLevelItem::class.java, "type")
            .registerSubtype(Story::class.java, "story")
            .registerSubtype(Detail::class.java, "detail")

    return GsonBuilder()
            .registerTypeAdapterFactory(dataAdapter)
            .create()
}

使用 Gson 创建一个 Converter.Factory 以改造为 addConverterFactory

fun getGsonConverterFactory(): Converter.Factory {
    return GsonConverterFactory.create(createCustomeDataGson())
}

fun <T> createRetrofitService(clazz: Class<T>,
                              baseUrl: String,
                              okHttpClient: OkHttpClient): T {
    val restAdapter = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addConverterFactory(getGsonConverterFactory())
            .build()
    return restAdapter.create(clazz)
}

终于创建了改造服务:

fun createCustomeDataApiApi(): CustomeDataApi {
    val baseUrl = getBaseUrl(defaultBaseUrl)
    return createRetrofitService(CustomeDataApi::class.java, baseUrl, okHttpClient)
}

internal interface CustomeDataApi {
    @GET("/api/customedata")
    fun getCustomData(@QueryMap params: Map<String, String>?): Call<DataResponse>
}

它以这种方式工作。 但是有些用例不使用retorfit 并且只有一个 json 字符串,并且想使用gson.fromJson&lt;T&gt;(jsonString, dataClassType), 如何配置gson以通过json中的“类型”生成类?

【问题讨论】:

    标签: gson runtimetypeadapterfactory


    【解决方案1】:

    查找样本here

    String responseJson = new String(responseBody); // from the service endpoint
    
    // which format has the response of the server
    final TypeToken<ServiceResponse> requestListTypeToken = new 
    TypeToken<ServiceResponse>() {};
    
    // adding all different container classes with their flag
    final RuntimeTypeAdapterFactory<AbstractContainer> typeFactory = 
    RuntimeTypeAdapterFactory  
        .of(Animal.class, "type") // Here you specify which is the parent class and what field particularizes the child class.
        .registerSubtype(Dog.class, "dog") // if the flag equals the class name, you can skip the second parameter. This is only necessary, when the "type" field does not equal the class name.
        .registerSubtype(Cat.class, "cat");
    
    // add the polymorphic specialization
    final Gson gson = new 
    GsonBuilder().registerTypeAdapterFactory(typeFactory).create();
    
    // do the mapping
    final ServiceResponse deserializedRequestList = gson.fromJson(responseJson, requestListTypeToken.getType() ); 
    

    不知道为什么它需要gson.fromJson(responseJson, requestListTypeToken.getType() );,它可以由

    gson.fromJson(responseJson, ServiceResponse.class);
    

    ?有什么区别?

    一些参考:1;2;3;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 2014-01-12
      • 2019-06-13
      相关资源
      最近更新 更多