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.
InstanceCreator
invokesWorkshift(Context)
that already instantiates aVisit
. So, i don't understand where the problem is. Do you want to modify this structure ?? – MccullyWorkshift
object to set its own reference inside its visit object. Currently, the workshift field insideVisit
turns out to be null when deserialized. – HyalineWorkshift.visit
and either : - makeVisit
a nested class ofWorkshift
- changeWorkshift.visit
visibility to default and have the two classes be in the same package. – Mccully