json 字符串中一个 value 多种类型的反序列化

json 字符串中一个 value 多种类型的反序列化

1. json 格式
{
    "ct":{
        "id":121605,
        "type":"type_str",
        "sample_data":["2119"]
    }
}

或者

{
    "data":{
    "ct":{
        "id":121605,
        "type":"type_factory",
        "sample_data":[
            {
                "factory":"beijing"
            },{
                "factory":"shanghai"
            }
        ]
    }
}

即 sample_data 的 value 可能是 List 类型的,也可能是 List 类型的,ct 的 value 对象对应的 javaBean 为 CtBean,为了保证 sample_data 既能兼容 String 又能兼容 FactoryDataBean,所以要添加泛型类型 CTGL_TYPE

class CtBean {
    var id = 0
    var sample_data : List? = null

    class FactoryDataBean {
        var factory : String? = null
    }
}
2. 自定义 JsonSerializer

自定义 JsonSerializer 来告诉 Gson 如何将指定的 json 字符串 反序列化为指定的类型/序列化为 Json 字符串。

方式一

直接反序列化为一种类型,如果类型转换失败则再转换为另一种类型,适用于没有 type 的情况,如果多次转换会消耗性能。

class CtSerializer : JsonSerializer>, JsonDeserializer> {

    override fun serialize(src: CtBean?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
        return Gson().toJsonTree(src)
    }

    override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): CtBean? {
        kotlin.runCatching {
            return Gson().fromJson(json, object : TypeToken>() {}.type)
        }.onFailure {
            return Gson().fromJson(json, object : TypeToken>(){}.type)
        }
        return Gson().fromJson(json, object : TypeToken>() {}.type)
    }
}

方式二

通过 type 来判断究竟反序列化为哪种类型

class CtSerializer : JsonSerializer>, JsonDeserializer> {

    override fun serialize(src: CtBean?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
        return Gson().toJsonTree(src)
    }

    override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): CtBean {
        var type = json.asJsonObject.getAsJsonPrimitive("type")?.asString
        if ("type_str".equals(type)) {
            return Gson().fromJson(json, object : TypeToken>(){}.type)
        } else if ("type_factory".equals(type)) {
            return Gson().fromJson(json, object : TypeToken>(){}.type)
        }
        return Gson().fromJson(json, object : TypeToken>() {
        }.type)
    }

}
3. 注册自定义的 JsonSerializer
    private static Retrofit getRetrofitInstance() {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(CtBean.class, new CtSerializer())
                .create();
        if (mRetrofit == null) {
            synchronized (HTTPCenter.class) {
                if (mRetrofit == null) {
                    mRetrofit = new Retrofit.Builder()
                            .baseUrl(HTTPService.Companion.getServiceDefault())
                            .addConverterFactory(GsonConverterFactory.create(gson))
                            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                            .client(initOkHttpClient()).build();
                }
            }
        }
        return mRetrofit;
    }
4. 解决 java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to xxx.bean.AssembleDetailCtBean$LCtglCsgsqyBean

解决方案:先把 linkedTreeMap 对象转成 json 字符串,然后再转成 JavaBean

Gson gson = new Gsonbuilder.enableComplexMapKeySerialization().create();
String jsonString = gson.toJson(linkedTreeMap);
JavaBean bean = gson.fromJson(jsonString,JavaBean.class);

实际应用如下:

private fun transTreeMapToRealObj(model: AssembleDetailEntity?) {
    kotlin.runCatching {
        GsonBuilder().enableComplexMapKeySerialization().create().let { gson ->
            model?.data?.tags?.let {
                val tagResultArrayList: ArrayList = ArrayList()
                for (ele in it) {
                    if (ele !is String) {
                        val tagsResultBean: AssembleDetailDataBean.TagsBean = gson.fromJson(gson.toJson(ele as LinkedTreeMap<*, *>), AssembleDetailDataBean.TagsBean::class.java)
                        tagResultArrayList.add(tagsResultBean)
                    }
                }
                if (tagResultArrayList.isNotEmpty()) {
                    model.data?.tags = tagResultArrayList
                }
            }
        }
    }.onFailure {
        TLog.e("TAG","transTreeMapToRealObj failed msg=" + it.message)
    }
}

你可能感兴趣的:(json 字符串中一个 value 多种类型的反序列化)