英文:
Gson Deserializing Problem - If Type parameter is child class could not deserialize
问题
在变量 Generic<Parent> generic
的 Master 类中,我在 main()
中传递了一个 Child 对象。在序列化过程中,我得到了正确的输出。但是在反序列化时,Child 对象丢失了。有人能给予建议。
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);
/*
* 输出: {"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 对象丢失
* 输出: {"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;
}
}
}
英文:
In Master class for the variable Generic<Parent> generic
i am passing a Child Object in main()
. During serializing i am getting correct output. But while deserializing Child Object is missing. Could anyone give suggesstions.
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;
}
}
}
答案1
得分: 1
问题
Gson尝试将泛型值反序列化为Parent
,而不是Child
。由于type
为null
,您可以看到反序列化后的对象中没有数据,看起来是{}
。如果您添加child.setType("type");
,则输出变为:
valMaster1
:{"id":2,"generic":{"t":{"name":"I am child","type":"type"}}}
valMaster2
:{"id":2,"generic":{"t":{"type":"type"}}}
然而,字段name
不在Parent
类中,而在Child
类中,Gson根本不知道它是Parent
的哪个子类(如果是的话),并且完全忽略该值,这是正确的行为。
解决方案
我基本上找到了两种选择(为了简洁起见,我使用了全参构造函数):
-
将上界泛型类型参数提升到
Master
类,并在反序列化时使用com.google.gson.reflect.TypeToken
和java.lang.reflect.Type
指定特定的Child
类型:static class Master<T extends Parent> { private int id; private Generic<T> generic; /* 获取器,设置器和全参构造函数 */ }
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"}}}
-
在
Master
类内部硬编码特定的泛型类型Generic<Child>
。反序列化变得更容易,但设计较不灵活:static class Master { private int id; private Generic<Child> generic; /* 获取器,设置器和全参构造函数 */ }
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"}}}
英文:
Problem
Gson tries to deserialize the generic value into Parent
, not Child
. Since there is type
as null
, you can see no data in the object deserialized which appears as {}
. If you add child.setType("type");
then the outputs become:
valMaster1
:{"id":2,"generic":{"t":{"name":"I am child","type":"type"}}}
valMaster2
:{"id":2,"generic":{"t":{"type":"type"}}}
However, the field name
is not present in the Parent
class but the Child
class and Gson simply has no idea what subclass of Parent
it is (if so) and completely ignores the value, which is a correct behavior.
Solution
I find basically two choices (I use all-args constructor for sake of brevity):
-
Elevate the upper-bounded generic type parameter to the
Master
class and specify the particularChild
type at the point of deserialization usingcom.google.gson.reflect.TypeToken
andjava.lang.reflect.Type
:static class Master<T extends Parent> { private int id; private Generic<T> generic; /* getters, setters and all-args constructor */ }
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"}}}
-
Hardcode the particular generic type
Generic<Child>
inside theMaster
class. The deserialization gets the way easier, yet the design is less flexible: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"}}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论