我遇到了一个问题,我需要在反序列化期间使用 Gson
和 InstanceCreator
将正在解析的对象的引用设置为其子对象。
为了描述问题,以下是类结构的简单表示。
public class Workshift {
private final transient Context context;
private final Visit visit;
public Workshift(Context context) {
this.context = context;
this.visit = new Visit(this);
}
}
public class Visit {
private final transient Workshift workshift;
public Visit(Workshift ws) {
this.workshift = ws;
}
}
通过这种结构,我可以通过向我的 GsonBuilder
提供一个 InstanceCreator
来在 Workshift
中设置 Context
,例如:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Workshift.class, new InstanceCreator<Workshift>() {
@Override
public Workshift createInstance(Type type) {
return new Workshift(context);
}
})
.create();
我知道,我可以向我的 GsonBuilder
添加额外的 InstanceCreator
,但我不确定如何提供我的 Workshift
的引用正在(即时)解析为 Visit
对象的对象?
如有任何帮助,我们将不胜感激!
最佳答案
你绝对应该使用 GraphAdapterBuilder .
正如您在@Braj 的回答下的评论中所说,
workshift is set transient for a reason so that it won't serialize this object when serializing visit object. If its not marked as transient then the serialization falls into stack overflow exception - by creating an unstoppable loop
这有一个简单的解决方案。
Workshift.java
public class Workshift {
private final transient Context context;
private final Visit visit;
//for testing
private String workshift_description;
public Workshift(Context context,String id) {
this.workshift_description=id;
this.context = context;
this.visit = new Visit(this);
}
public String getId() {
return workshift_description;
}
public void setId(String id) {
this.workshift_description = id;
}
public String toString() {
return "[Workshift element => { WD: "+this.workshift_description+", VD : "+this.visit.getVisit_description()+"}";
}
}
访问.java
public class Visit {
private final /* transient */ Workshift workshift;
public Visit(Workshift ws) {
this.workshift = ws;
}
public String getVisit_description() {
return "visit containing "+ workshift.getId();
}
}
诀窍就在这里:
GsonBuilder gsonBuilder = new GsonBuilder();
new GraphAdapterBuilder()
.addType(Visit.class)
.addType(Workshift.class)
.registerOn(gsonBuilder);
把所有的东西放在一起,
public static void main(String[] args) {
Workshift[] workshifts = new Workshift[10];
for (int i = 0; i < workshifts.length; i++) {
//Replace Context(i) for the real one
workshifts[i] = new Workshift(new Context(i), "Workshift#"
+ i);
}
System.out.println("Original Workshifts array:");
for (int i = 0; i < workshifts.length; i++) {
System.out.println(workshifts[i]);
}
System.out.println("===================================");
GsonBuilder gsonBuilder = new GsonBuilder();
new GraphAdapterBuilder()
.addType(Visit.class)
.addType(Workshift.class)
.registerOn(gsonBuilder);
Gson gson = gsonBuilder.setPrettyPrinting().create();
String serialized = gson.toJson(workshifts);
// System.out.println(serialized);
Workshift[] w_array = gson.fromJson(serialized, Workshift[].class);
// System.out.println(gson.toJson(w_array));
System.out.println("Des-serialized Workshifts array:");
for (int i = 0; i < w_array.length; i++) {
System.out.println(w_array[i]);
}
System.out.println("===================================");
输出:
Original Workshifts array:
[Workshift element => { WD: Workshift#0, VD : visit containing Workshift#0}
[Workshift element => { WD: Workshift#1, VD : visit containing Workshift#1}
[Workshift element => { WD: Workshift#2, VD : visit containing Workshift#2}
[Workshift element => { WD: Workshift#3, VD : visit containing Workshift#3}
[Workshift element => { WD: Workshift#4, VD : visit containing Workshift#4}
[Workshift element => { WD: Workshift#5, VD : visit containing Workshift#5}
[Workshift element => { WD: Workshift#6, VD : visit containing Workshift#6}
[Workshift element => { WD: Workshift#7, VD : visit containing Workshift#7}
[Workshift element => { WD: Workshift#8, VD : visit containing Workshift#8}
[Workshift element => { WD: Workshift#9, VD : visit containing Workshift#9}
===================================
Des-serialized Workshifts array:
[Workshift element => { WD: Workshift#0, VD : visit containing Workshift#0}
[Workshift element => { WD: Workshift#1, VD : visit containing Workshift#1}
[Workshift element => { WD: Workshift#2, VD : visit containing Workshift#2}
[Workshift element => { WD: Workshift#3, VD : visit containing Workshift#3}
[Workshift element => { WD: Workshift#4, VD : visit containing Workshift#4}
[Workshift element => { WD: Workshift#5, VD : visit containing Workshift#5}
[Workshift element => { WD: Workshift#6, VD : visit containing Workshift#6}
[Workshift element => { WD: Workshift#7, VD : visit containing Workshift#7}
[Workshift element => { WD: Workshift#8, VD : visit containing Workshift#8}
[Workshift element => { WD: Workshift#9, VD : visit containing Workshift#9}
===================================
没有 StackOverflow 错误。
如果你取消注释该行
// System.out.println(serialized);
输出是这样的:
[
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#0"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#1"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#2"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#3"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#4"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#5"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#6"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#7"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#8"
},
"0x2": {
"workshift": "0x1"
}
},
{
"0x1": {
"visit": "0x2",
"workshift_description": "Workshift#9"
},
"0x2": {
"workshift": "0x1"
}
}
]
那是因为 Gson 正在替换您的引用,以避免堆栈溢出异常。这就像模拟指针
希望对您有所帮助。
注意:记得复制文件 GraphAdapterBuilder.java 并更改行
private final ConstructorConstructor constructorConstructor = new ConstructorConstructor();
与
private final ConstructorConstructor constructorConstructor = new ConstructorConstructor(instanceCreators);
否则无法编译。也许现在就修好了。
关于java - Gson - 使用 InstanceCreator 即时设置对象引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22071565/