如何使用gson.fromJson()基于json字符串的数据构建Gson以创建不同的pojo类

时间:2019-04-02 23:48:09

标签: gson runtimetypeadapterfactory

当使用改造从远程获取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
    }
]
}

通过改型,可以由addConverterFactoryConverter.Factory完成,例如: 这里用RuntimeTypeAdapterFactory构建dataAdapter来创建Gson并要求根据“类型”创建calsons

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<T>(jsonString, dataClassType), 如何配置gson以通过json中的“类型”生成类?

1 个答案:

答案 0 :(得分:0)

找到一个示例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;