I\'m stuck in a problem where I need to set reference of my object being parsed to its child objects during deserialization using Gson
and InstanceCreator
You should definitely use GraphAdapterBuilder.
As you said in the comment under @Braj 's answer,
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
This has a simple solution.
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()+"}";
}
}
Visit.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();
}
}
The trick resides here:
GsonBuilder gsonBuilder = new GsonBuilder();
new GraphAdapterBuilder()
.addType(Visit.class)
.addType(Workshift.class)
.registerOn(gsonBuilder);
Putting all together,
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("===================================");
Output:
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}
===================================
There's no StackOverflow error.
if you un-comment the line
// System.out.println(serialized);
The output would be like this:
[
{
"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"
}
}
]
That's because Gson is replacing your references, in order to avoid that stack overflow exception. It's like emulating pointers
Hope it helps.
Note: Remember to copy the files GraphAdapterBuilder.java and change the line
private final ConstructorConstructor constructorConstructor = new ConstructorConstructor();
with
private final ConstructorConstructor constructorConstructor = new ConstructorConstructor(instanceCreators);
It won't compile otherwise. Maybe it's fixed right now.