简体   繁体   中英

Gson fails to deserialize with custom serializer

I wrote a custom (de)serializer so I could serialize my ArrayList of an interface. Here is the serializer:

package com.darkraven.shoppinglist;

import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.*;
import java.lang.reflect.Type;

class InterfaceAdapter<Item> implements JsonSerializer<Item>, JsonDeserializer<Item> {
    public JsonElement serialize(Item object, Type interfaceType, JsonSerializationContext context) {
        final JsonObject wrapper = new JsonObject();
        wrapper.addProperty("type", object.getClass().getName());
        wrapper.add("data", context.serialize(object));
        return wrapper;
    }

    public Item deserialize(JsonElement elem, Type interfaceType, JsonDeserializationContext context) throws JsonParseException {
        final JsonObject wrapper = (JsonObject) elem;
        final JsonElement typeName = get(wrapper, "type");
        final JsonElement data = get(wrapper, "data");
        final Type actualType = typeForName(typeName);
        return context.deserialize(data, actualType);
    }

    private Type typeForName(final JsonElement typeElem) {
        try {
            return Class.forName(typeElem.getAsString());
        } catch (ClassNotFoundException e) {
            throw new JsonParseException(e);
        }
    }

    private JsonElement get(final JsonObject wrapper, String memberName) {
        final JsonElement elem = wrapper.get(memberName);
        if (elem == null) throw new JsonParseException("no '" + memberName + "' member found in what was expected to be an interface wrapper");
        return elem;
    }
}

Here is the Item interface, the one to be serialized:

public interface Item extends Parcelable, Serializable{
}

And here are the two implementations of Item :

public class Category implements Item{

    String name;
    int color;

    //irrelevant methods
}

public class Product implements Item{

    String name;
    int color;
    Category category;

    //irrelevant methods
}

I get this error on the console:

09-05 10:33:42.613  28602-28602/? W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.get(InterfaceAdapter.java:34)
09-05 10:33:42.613  28602-28602/? W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.deserialize(InterfaceAdapter.java:18)
09-05 10:33:42.613  28602-28602/? W/System.err: at com.darkraven.shoppinglist.ShoppingList.readItemArrayList(ShoppingList.java:216)
09-05 10:33:42.613  28602-28602/? W/System.err: at com.darkraven.shoppinglist.ShoppingList.onCreate(ShoppingList.java:37)

The lines are:

if (elem == null) throw new JsonParseException("no '" + memberName + "' member found in what was expected to be an interface wrapper");
final JsonElement typeName = get(wrapper, "type");

What is the problem?

Edit: full stacktrace:

09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: com.google.gson.JsonParseException: no 'type' member found in what was expected to be an interface wrapper
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.get(InterfaceAdapter.java:35)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.deserialize(InterfaceAdapter.java:18)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.Gson.fromJson(Gson.java:803)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.Gson.fromJson(Gson.java:768)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.ShoppingList.readItemArrayList(ShoppingList.java:216)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.ShoppingList.onCreate(ShoppingList.java:37)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.Activity.performCreate(Activity.java:5207)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
09-05 10:44:45.791  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2281)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist D/dalvikvm: GC_FOR_ALLOC freed 227K, 3% free 11287K/11536K, paused 19ms, total 19ms
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:148)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1263)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at android.os.Looper.loop(Looper.java:137)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5124)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at java.lang.reflect.Method.invoke(Method.java:525)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-05 10:44:45.811  29102-29102/com.darkraven.shoppinglist W/System.err: at dalvik.system.NativeStart.main(Native Method)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: com.google.gson.JsonParseException: no 'data' member found in what was expected to be an interface wrapper
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.get(InterfaceAdapter.java:35)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.deserialize(InterfaceAdapter.java:19)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.Gson.fromJson(Gson.java:803)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.Gson.fromJson(Gson.java:768)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.ShoppingList.readItemArrayList(ShoppingList.java:216)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.ShoppingList.onCreate(ShoppingList.java:37)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.Activity.performCreate(Activity.java:5207)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2281)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:148)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1263)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.os.Looper.loop(Looper.java:137)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5124)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at java.lang.reflect.Method.invoke(Method.java:525)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at dalvik.system.NativeStart.main(Native Method)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: java.lang.NullPointerException
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.typeForName(InterfaceAdapter.java:26)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.InterfaceAdapter.deserialize(InterfaceAdapter.java:20)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.Gson.fromJson(Gson.java:803)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.google.gson.Gson.fromJson(Gson.java:768)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.ShoppingList.readItemArrayList(ShoppingList.java:216)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.darkraven.shoppinglist.ShoppingList.onCreate(ShoppingList.java:37)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.Activity.performCreate(Activity.java:5207)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2281)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:148)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1263)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.os.Looper.loop(Looper.java:137)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5124)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at java.lang.reflect.Method.invoke(Method.java:525)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-05 10:44:45.821  29102-29102/com.darkraven.shoppinglist W/System.err: at dalvik.system.NativeStart.main(Native Method)

Edit: writing method:

public void writeItemArrayList(){
        try{
            File file = new File(this.getFilesDir(), "shoppinglist.json");
            Gson gson = new GsonBuilder().registerTypeAdapter(Item.class, new InterfaceAdapter<Item>())
                    .create();
            FileWriter writer = new FileWriter(file);
            writer.write(gson.toJson(items));
            writer.flush();
            writer.close();
        }catch (Exception e){

        }

    }

Reading method:

public void readItemArrayList(){
        try{
            FileReader reader = new FileReader(new File(this.getFilesDir(), "shoppinglist.json"));
            Gson gson = new GsonBuilder().registerTypeAdapter(Item.class, new InterfaceAdapter<Item>())
                    .create();
            this.items = gson.fromJson(reader, new TypeToken<ArrayList<Item>>(){}.getType());
            reader.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

Look at GSON not calling my TypeAdapter for a type which is an interface

I got your code working with by using registerTypeHierarchyAdapter noted from the link , I posted all of it because I had to make a change in your serialize method so I didn't get a stack overflow exception.

public void writeItemArrayList(){
    try{
        File file = new File(this.getFilesDir(), "shoppinglist.json");
        /*change here*/Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Item.class, new InterfaceAdapter<Item>())
                .create();
        FileWriter writer = new FileWriter(file);
        writer.write(gson.toJson(items));
        writer.flush();
        writer.close();
    }catch (Exception e){

    }

}

public void readItemArrayList(){
    try{
        FileReader reader = new FileReader(new File(this.getFilesDir(), "shoppinglist.json"));
        Gson gson = new GsonBuilder().registerTypeAdapter(Item.class, new InterfaceAdapter<Item>())
                .create();
        this.items = gson.fromJson(reader, new TypeToken<ArrayList<Item>>(){}.getType());
        reader.close();
    } catch(Exception e){
        e.printStackTrace();
    }
}

class InterfaceAdapter<Item> implements JsonSerializer<Item>, JsonDeserializer<Item> {
    public JsonElement serialize(Item object, Type interfaceType, JsonSerializationContext context) {
        final JsonObject wrapper = new JsonObject();
        System.out.println("serialize " + object);
        wrapper.addProperty("type", object.getClass().getName());
        /*change here*/Gson gson = new Gson();
        /*change here*/wrapper.add("data", gson.toJsonTree(object, interfaceType));
        return wrapper;
    }
    ....... same code as before below .......
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM