java - Gson 无法使用自定义序列化程序进行反序列化

标签 java android serialization gson

我编写了一个自定义(反)序列化器,因此我可以序列化我的接口(interface)的 ArrayList。这是序列化程序:

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;
    }
}

这里是Item接口(interface),就是要序列化的接口(interface):

public interface Item extends Parcelable, Serializable{
}

下面是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
}

我在控制台上收到此错误:

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)

行是:

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");

问题是什么?

编辑:完整堆栈跟踪:

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)

编辑:写法:

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){

        }

    }

阅读方法:

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();
        }
    }

最佳答案

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

我通过使用链接中提到的 registerTypeHierarchyAdapter 来处理你的代码,我发布了所有代码,因为我必须对你的序列化方法进行更改,所以我没有得到堆栈溢出异常。

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 .......
}

关于java - Gson 无法使用自定义序列化程序进行反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18631542/

相关文章:

java - 抽象测试类

java - 有没有办法在 Java 中找出映射的驱动器?

android - 在 getrrsetbyname.c 中交叉编译适用于 Android 的 OpenSSH 失败

强调 ListView 行的 Android ICS 指南

java - 序列化 ECJ GP individual 以供以后执行

java - Log4j 定义多个记录器

java - 使用 java 配置的 TCP 客户端缺少 bean 工厂

android - 如何在没有 android studio 的情况下签署 android apk

php - 在 PHP 中序列化或散列闭包

c# - 从 BsonDocument 反序列化为字符串并序列化回 BsonDocument