google gson将LinkedTreeMap类强制转换为myclass

时间:2015-09-07 19:18:40

标签: java android gson

我之前已经问过这个问题。由于我在java和android的新手技巧。一个多星期以来,我无法解决这个问题。

我的一个朋友和我正在开发一个Android项目是有这样的事情。

这件事最奇怪的部分是,它发生在我从Google Play商店下载和测试时。不是从本地android studio安装或调试模式。

这可能是什么问题,或者这个完全错误的返回列表? 我的朋友说服这段代码正确返回但是从Play商店安装它始终是一个错误。

请建议我在哪里继续挖掘?

@Override
public void promiseMethod(JSONObject object) {
    if (object != null) {

        if (object.has(DO_SERVICES)) {
            vehicleDetails = new ArrayList < Object[] > (1);
            List < String > vehicleNoList = new ArrayList < String > (1);
            List < String > serviceList = new ArrayList < String > (1);
            try {
                Gson gson = new Gson();
                JSONObject jsonObj = new JSONObject(object.get(DO_SERVICES)
                    .toString());
                servDto = gson.fromJson(jsonObj.toString(),
                    ServiceDto.class);


                if (servDto.getServiceDto() instanceof List) {

                    List < DoServiceDto > doServiceList = servDto.getServiceDto();

例外是

  

java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法强制转换为com.gaurage.dto.DoServiceDto     在com.gaurage.user.User_Test_Main.promiseMethod(未知来源)

5 个答案:

答案 0 :(得分:70)

序列化和反序列化通用类型

当你调用toJson(obj)时,Gson调用obj.getClass()来获取有关要序列化的字段的信息。类似地,您通常可以在fromJson(json,MyClass.class)方法中传递MyClass.class对象。如果对象是非泛型类型,则此方法正常。但是,如果对象是泛型类型,则由于Java类型擦除而丢失通用类型信息。这是一个说明这一点的例子:

class Foo<T> {  T value;}
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
gson.toJson(foo); // May not serialize foo.value correctly
gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar

上面的代码无法将值解释为类型Bar,因为Gson调用list.getClass()来获取其类信息,但此方法返回一个原始类Foo.class。这意味着Gson无法知道这是Foo类型的对象,而不仅仅是普通的Foo。

您可以通过为通用类型指定正确的参数化类型来解决此问题。您可以使用TypeToken类来完成此操作。

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();    
gson.toJson(foo, fooType);
gson.fromJson(json, fooType);

我有父类和它的子类,其中一些包含List类型。像这个父类我有30个文件。我这样解决了。

Gson gson = new Gson();
JSONObject jsonObj = new JSONObject(object.get(DO_SERVICES).toString());
Type type = new TypeToken<MyDto>() {}.getType();
servDto = gson.fromJson(jsonObj.toString(),type);

最重要的是,我无法在Android工作室的本地测试中重现此错误。此问题仅弹出,当我生成签名的apk并将应用程序发布到PlayStore时,应用程序停止,并且报告说无法将LinkedTreeMap强制转换为myclass。

我很难在本地测试中重现相同的结果(包括调试模式)。

答案 1 :(得分:1)

EngineSense的答案是正确的。
但是,如果您仍然想使用泛型并且不想将具体的类类型作为参数传递,那么下面是Kotlin中的一种变通方法示例。
(请注意,带有类型化类型参数的内联方法不能从Java调用)

可能不是完成任务的最有效方法,但它确实有效。


以下是GsonUtil.kt

inline fun <reified T> fromJson(json: String): T? {
    return gson.fromJson(json, object : TypeToken<T>() {}.type)
}

fun <T> mapToObject(map: Map<String, Any?>?, type: Class<T>): T? {
    if (map == null) return null

    val json = gson.toJson(map)
    return gson.fromJson(json, type)
}

检索通用对象的轻量级列表的方法。

inline fun <reified T: MyBaseClass> getGenericList(): List<T> {
    val json = ...

    //Must use map here because the result is a list of LinkedTreeMaps
    val list: ArrayList<Map<String, Any?>>? = GsonUtil.fromJson(json)
    //handle type erasure
    val result = list?.mapNotNull {
        GsonUtil.mapToObject(it, T::class.java)
    }

    return  result ?: listOf()
}

答案 2 :(得分:0)

Source

在我的 ListView BaseAdapter 中遇到相同的问题

JSON格式以显示

{
    results: [
    {
        id: "10",
        phone: "+91783XXXX345",
        name: "Mr Example",
        email: "freaky@jolly.com"
    },
    {
        id: "11",
        phone: "+9178XXXX66",
        name: "Mr Foo",
        email: "freaky@jolly.com"
    }],
    statusCode: "1",
    count: "2"
}

我遇到了这个问题

  

E / Android运行时:致命异常:主要                     流程:com.hsa.ffgp.hapdfgdfgoon,PID:25879                     java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法转换为   com.hsa .......

然后我使用 LinkedTreeMap 键值如下映射数据

...
...

    @Override
    public View getView(final int i, View view, ViewGroup viewGroup) {
        if(view==null)
        {
            view= LayoutInflater.from(c).inflate(R.layout.listview_manage_clients,viewGroup,false);
        }

        TextView mUserName = (TextView) view.findViewById(R.id.userName);
        TextView mUserPhone = (TextView) view.findViewById(R.id.userPhone);


        Object getrow = this.users.get(i);
        LinkedTreeMap<Object,Object> t = (LinkedTreeMap) getrow;
        String name = t.get("name").toString();

        mUserName.setText("Name is "+name);
        mUserPhone.setText("Phone is "+phone);

        return view;
    }
...
...

答案 3 :(得分:0)

就我而言,从共享首选项中获取对象列表时发生错误。  通过添加TypeToken如下所示解决了该错误:

 public static <GenericClass> GenericClass getListOfObjectsFromSharedPref(Context context,String preferenceFileName, String preferenceKey ){

    SharedPreferences sharedPreferences = 
    context.getSharedPreferences(preferenceFileName, 0);
    Type type = new TypeToken<ArrayList<Classname.class>>() {}.getType();
    String json = sharedPreferences.getString(preferenceKey, "");
    final Gson gson = new Gson();
    return gson.fromJson(json, type);
}

....

答案 4 :(得分:0)

导入
import com.google.gson.Gson;
导入com.google.gson.reflect.TypeToken;

代码
String json = new Gson()。toJson(“ Your Value”);
ArrayList outputList =新的Gson()。fromJson(“接收值”,新的TypeToken (){ } .getType());

Log.d(“ TAG”,outputList.get(0).getName);