使用gson反序列化接口数据而不是返回值?

时间:2018-04-17 04:39:08

标签: java gson

我正在进行下面的简单实验测试。

public class MyTest {

    @Test
    public void testing() {
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(SubData.class, new SubDataImplInstanceCreator());
        Gson gson = builder.create();

        Dataclass data = new Dataclass();
        data.key1 = "abc";
        SubDataImpl subData = new SubDataImpl();
        subData.hello = "ttt";
        data.sub = subData;
        String jsonValue = gson.toJson(data);
        System.out.println(jsonValue);

        Dataclass data2 = gson.fromJson(jsonValue, Dataclass.class);
        System.out.println(gson.toJson(data2));

    }

    class Dataclass implements Serializable {
        String key1;
        SubData sub;
    }

    interface SubData {
        String getHello();
    }

    class SubDataImpl implements SubData, Serializable {

        String hello;

        @Override
        public String getHello() {
            return hello;
        }
    }


    public class SubDataImplInstanceCreator implements InstanceCreator<SubDataImpl> {
        @Override
        public SubDataImpl createInstance(Type type) {
            return new SubDataImpl();
        }
    }
}

我希望它能够回归

{"key1":"abc","sub":{"hello":"ttt"}}
{"key1":"abc","sub":{"hello":"ttt"}}

因为它们基本上是序列化和反序列化的相同数据。

但是,当我运行它时,我得到了

{"key1":"abc","sub":{"hello":"ttt"}}
{"key1":"abc","sub":{}}

为什么在反序列化Json字符串后,我放弃了SubData值?我的代码中遗漏了什么吗?

2 个答案:

答案 0 :(得分:2)

您似乎已经点击此bug,建议的解决方案是使用TypeAdapter作为界面。

快速而肮脏的实施(使用它代替SubDataImplInstanceTypeAdapter)

 public class SubDataImplInstanceTypeAdapter implements JsonDeserializer<SubDataImpl>, JsonSerializer<SubDataImpl> {


    @Override
    public SubDataImpl deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        SubDataImpl impl = new SubDataImpl();
        JsonObject object = json.getAsJsonObject();
        impl.setHello(object.get("hello").getAsString());
        return impl;

    }

    @Override
    public JsonElement serialize(SubDataImpl src, Type typeOfSrc, JsonSerializationContext context) {
        return context.serialize(src);
    }
}

答案 1 :(得分:0)

我使用以下

public class MyTest {
    @Test
    public void testing() {
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(SubData.class, new SubDataTypeAdapter());
        Gson gson = builder.create();

        Dataclass data = new Dataclass();
        data.key1 = "abc";
        SubDataImpl subData = new SubDataImpl();
        subData.hello = "ttt";
        data.sub = subData;
        String jsonValue = gson.toJson(data);
        System.out.println(jsonValue);

        Dataclass data2 = gson.fromJson(jsonValue, Dataclass.class);
        System.out.println(gson.toJson(data2));
    }

    class SubDataTypeAdapter extends TypeAdapter<SubDataImpl> {

        @Override
        public void write(JsonWriter out, final SubDataImpl subData) throws IOException {
            out.beginObject();
            out.name("hello").value(subData.getHello());
            out.endObject();
        }

        @Override
        public SubDataImpl read(JsonReader in) throws IOException {
            final SubDataImpl subData = new SubDataImpl();

            in.beginObject();
            while (in.hasNext()) {
                switch (in.nextName()) {
                    case "hello":
                        subData.hello = in.nextString();
                        break;
                }
            }
            in.endObject();

            return subData;
        }
    }

    class Dataclass implements Serializable {
        String key1;
        SubData sub;
    }

    abstract class SubData {
        abstract String getHello();
    }

    class SubDataImpl extends SubData implements Serializable {

        String hello;

        @Override
        public String getHello() {
            return hello;
        }
    }
}