web-dev-qa-db-ja.com

google gson LinkedTreeMapクラスをmyclassにキャスト

この質問は以前に聞かれたことを知っていました。 JavaおよびAndroidの初心者スキルがあるため、この問題は1週間以上解決できません。

私の友人と私はAndroidプロジェクトを開発していましたが、このようなものがいくつかありました。

このことの最も奇妙な部分は、Google Playストアからダウンロードしてテストしたときにのみ発生することです。ローカルからではありませんAndroidスタジオのインストールまたはデバッグモード。

ここで何が問題になるのでしょうか?私の友人は、このコードは正しく返されると確信していますが、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.user.User_Test_Main.promiseMethod(Unknown Source)でcom.gaurage.dto.DoServiceDtoにキャストできません

22
Tot

ジェネリック型のシリアル化と逆シリアル化

ToJson(obj)を呼び出すと、Gsonはobj.getClass()を呼び出して、シリアル化するフィールドに関する情報を取得します。同様に、通常はfromJson(json、MyClass.class)メソッドでMyClass.classオブジェクトを渡すことができます。オブジェクトが非ジェネリック型の場合、これは正常に機能します。ただし、オブジェクトがジェネリック型である場合、Java Type Erasureのため、ジェネリック型情報は失われます。ポイントを示す例は次のとおりです。

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

上記のコードは、Gsonがlist.getClass()を呼び出してクラス情報を取得するため、値をBar型として解釈できませんが、このメソッドは生のクラスFoo.classを返します。つまり、Gsonには、これが単なるFooではなく、Foo型のオブジェクトであることを知る方法がありません。

ジェネリック型に正しいパラメーター化された型を指定することにより、この問題を解決できます。これを行うには、TypeTokenクラスを使用します。

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

私には親クラスがあり、その中にはリスト型を持つ子クラスがあります。この親クラスのように、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 studioからのローカルテストでこのエラーを再現できないことです。アプリが停止し、レポートに「LinkedTreeMapをmyclassにキャストできません」と表示されます

ローカルテスト(デバッグモードを含む)で同じ結果を再現するのは困難でした。

80
Tot

ソース

MyListView BaseAdapterで同じ問題に直面している

表示するJSON形式

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

私はこの問題に直面していました

E/AndroidRuntime:致命的な例外:メインプロセス:com.hsa.ffgp.hapdfgdfgoon、PID:25879 Java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMapはcom.hsaにキャストできません......

次に、LinkedTreeMapKey Valueを使用してデータをマッピングしました

...
...

    @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;
    }
...
...
2
Code Spy

私の場合、共有設定からオブジェクトのリストを取得中にエラーが発生しました。以下に示すように、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);
}

....

0
Deepak Kataria