Java Gson反序列化问题-如果类型参数为子类,则无法反序列化

Java Gson反序列化问题-如果类型参数为子类,则无法反序列化,java,generics,gson,json-deserialization,Java,Generics,Gson,Json Deserialization,在变量Generic的Master类中,我正在main()中传递一个子对象。在序列化过程中,我得到了正确的输出。但在反序列化子对象时丢失。谁能给我一些建议 public class GenericSample { public static void main(String[] args) { Generic<Parent> generic = new Generic<Parent>(); Child child = new Chi

在变量
Generic
Master类中,我正在
main()
中传递一个子对象。在序列化过程中,我得到了正确的输出。但在反序列化子对象时丢失。谁能给我一些建议

public class GenericSample {
    public static void main(String[] args) {
        Generic<Parent> generic = new Generic<Parent>();
        Child child = new Child();
        child.setName("I am child");
        generic.setT(child);

        Gson gson = new Gson();

        Master master = new Master();
        master.setId(2);
        master.setGeneric(generic);

        String valMaster = gson.toJson(master);
        System.out.println(valMaster);
        /*
         * Output: {"id":2,"generic":{"t":{"name":"I am child"}}}
         */

        Master master2 = gson.fromJson(valMaster, Master.class);
        String valMaster2 = gson.toJson(master2);
        System.out.println(valMaster2);
        /*
         * Child Object is missing
         * Output: {"id":2,"generic":{"t":{}}}
         */
    }

    static class Master {
        private int id;
        private Generic<Parent> generic;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public Generic<Parent> getGeneric() {
            return generic;
        }

        public void setGeneric(Generic<Parent> generic) {
            this.generic = generic;
        }

    }

    static class Generic<T> {
        T t;

        public T getT() {
            return t;
        }

        public void setT(T t) {
            this.t = t;
        }
        
    }
    static class Parent {
        private String type;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

    }

    static class Child extends Parent {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

    }

}
public类GenericSample{
公共静态void main(字符串[]args){
泛型=新泛型();
子项=新子项();
child.setName(“我是孩子”);
generic.setT(儿童);
Gson Gson=新的Gson();
母版=新母版();
硕士学位证书(2);
硕士学位(通用);
字符串valMaster=gson.toJson(master);
系统输出打印LN(valMaster);
/*
*输出:{“id”:2,“generic”:{“t”:{“name”:“我是孩子”}}
*/
Master master2=gson.fromJson(valMaster,Master.class);
字符串valMaster2=gson.toJson(master2);
系统输出打印LN(valMaster2);
/*
*缺少子对象
*输出:{“id”:2,“generic”:{“t”:{}
*/
}
静态类主控{
私有int-id;
私有通用;
公共int getId(){
返回id;
}
公共无效集合id(内部id){
this.id=id;
}
公共泛型getGeneric(){
返回泛型;
}
公共void setGeneric(Generic-Generic){
this.generic=generic;
}
}
静态类泛型{
T;
公共T getT(){
返回t;
}
公共无效集合(T){
t=t;
}
}
静态类父类{
私有字符串类型;
公共字符串getType(){
返回类型;
}
公共void集合类型(字符串类型){
this.type=type;
}
}
静态类子级扩展父级{
私有字符串名称;
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
}
}

问题

Gson尝试将泛型值反序列化为
父级
,而不是
子级
。由于存在
type
null
,因此在显示为
{}
的反序列化对象中看不到任何数据。如果添加
child.setType(“type”)然后输出变为:

  • valMaster1
    {“id”:2,“generic”:{“t”:{“name”:“我是孩子”,“type”:“type”}}
  • valMaster2
    {“id”:2,“generic”:{“t”:{“type”:“type”}}
但是,
父类
中不存在字段
名称
,而
子类
类和Gson根本不知道它是
父类
的哪个子类(如果是),并且完全忽略该值,这是一种正确的行为

解决方案

我发现基本上有两种选择(为了简洁起见,我使用了所有参数构造函数):

  • 将上限泛型类型参数提升到
    主类
    类,并使用
    com.google.gson.reflect.TypeToken
    java.lang.reflect.type
    在反序列化点指定特定的
    子类
    类型:

    static class Master<T extends Parent> {
        private int id;
        private Generic<T> generic;
    
        /* getters, setters and all-args constructor */
    }
    
    Child-Child=新孩子(“我是孩子”);
    通用=新通用(子);
    母版=新母版(2,通用);
    Gson Gson=新的Gson();
    字符串valMaster=gson.toJson(master);
    系统输出打印LN(valMaster);
    //{“id”:2,“泛型”:{“t”:{“name”:“我是孩子”}}
    Master master2=gson.fromJson(valMaster,Master.class);
    字符串valMaster2=gson.toJson(master2);
    系统输出打印LN(valMaster2);
    //{“id”:2,“泛型”:{“t”:{“name”:“我是孩子”}}
    

  • 我确信OP要求的是完美的往返序列化/反序列化,而不是临时硬编码子类。@fluffy:你读过第一对代码片段了吗?它没有说硬编码。是的,我说了。有
    Type Type=new-TypeToken(){}.getType()在你的解决方案1中。请在我看来不错的位置找到一个往返解决方案。但是,您必须删除从父项声明的字段
    type
    。谢谢我学到了一些新东西。请随意添加答案。
    Child child = new Child("I am child");
    Generic<Parent> generic = new Generic<>(child);
    Master<Parent> master = new Master<>(2, generic);
    
    Gson gson = new Gson();
    String valMaster = gson.toJson(master);
    System.out.println(valMaster);                           
    // {"id":2,"generic":{"t":{"name":"I am child"}}}
    
    Type type = new TypeToken<Master<Child>>() {}.getType();
    Master<Child> master2 = gson.fromJson(valMaster, type);
    String valMaster2 = gson.toJson(master2);
    System.out.println(valMaster2);
    // {"id":2,"generic":{"t":{"name":"I am child"}}}
    
    
    static class Master {
        private int id;
        private Generic<Child> generic;
    
        /* getters, setters and all-args constructor */
    }
    
    Child child = new Child("I am child");
    Generic<Child> generic = new Generic<>(child);
    Master master = new Master(2, generic);
    
    Gson gson = new Gson();
    String valMaster = gson.toJson(master);
    System.out.println(valMaster);
    // {"id":2,"generic":{"t":{"name":"I am child"}}}
    
    Master master2 = gson.fromJson(valMaster, Master.class);
    String valMaster2 = gson.toJson(master2);
    System.out.println(valMaster2);
    // {"id":2,"generic":{"t":{"name":"I am child"}}}