Imagine that I have these classes:
public class A {
private B b;
}
public class B {
private A a;
}
And then I have this:
A a = new A();
B b = new B();
a.b = b;
b.a = a;
Gson gson = new Gson();
String x = gson.toJson(a);
The result is StackOverflowError
(trunquei it, but consists of a lot of repetitions of what is below):
java.lang.StackOverflowError at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source) at sun.reflect.UnsafeObjectFieldAccessorImpl.get(Unknown Source) at java.lang.reflect.Field.get(Unknown Source) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.writeField(ReflectiveTypeAdapterFactory.java:124) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:238) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:113) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:950) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:113) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:113) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:950) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:113) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:113) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:950)
There are several ways to resolve the circular reference in GSON, such as adding the transient
modifier, using some exclusion strategy, and so on. However all of these shapes only work after I already know where the circular reference is.
It occurs that I have a scenario where there is a set with a few hundred distinct classes related to being serialized in JSON format through GSON. In the middle of all these objects, there is at least one circular reference somewhere, but locating it is like looking for a needle in the haystack. I know that after identifying the circular reference, solving it must be relatively easy. How do I find out where this circular reference is?
Oh, and I'm on a project that is in maintenance and production phase so I can not simply decide to replace a bunch of technologies with others, introduce or delete libraries, or redesign a lot of things. If so, I would use Jackson instead of GSON, since Jackson clearly says where the circular reference is when it occurs.
I'm using GSON 2.5.