I have an object that contains a piece of data and associated exception.
Public class MyBean{
Private String data;
Private Exception problem;
.
.
.
}
When I try to GSON.toJSON(object) it gives me a circular references error complaining about the "problem" field.
Is there a way to for GSON to handle such objects ?
Gson does indeed complain about a circular reference error when attempting to serialize a data structure as described in the original question.
The following example demonstrates this point.
import com.google.gson.Gson;
public class GsonFoo
{
public static void main(String[] args)
{
MyBean bean = new MyBean();
bean.data = "some data";
bean.problem = new RuntimeException("Ack!");
System.out.println(new Gson().toJson(bean));
}
}
class MyBean
{
public String data;
public Exception problem;
}
This example results in the following exception and message from Gson.
Exception in thread "main" java.lang.IllegalStateException: circular reference error
Offending field: cause
Offending object: preserveType: false, type: class java.lang.Throwable, obj: java.lang.RuntimeException: Ack!
at com.google.gson.CircularReferenceException.createDetailedException(CircularReferenceException.java:43)
at com.google.gson.JsonSerializationVisitor.visitObjectField(JsonSerializationVisitor.java:117)
...
Gson similarly chokes when attempting something as simple as the following.
System.out.println(new Gson().toJson(new RuntimeException("Ack!")));
Gson does not currently have a configuration available to simply resolve this problem. I recommend logging an issue at http://code.google.com/p/google-gson/issues/list.
If an object with an Exception
reference must be serialized and if Gson must be used, then custom serialization processing for the Exception
reference must be implemented. Following is one such example.
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public class GsonFoo
{
public static void main(String[] args)
{
MyBean bean = new MyBean();
bean.data = "some data";
bean.problem = new RuntimeException("Ack!");
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Exception.class, new ExceptionSerializer());
Gson gson = gsonBuilder.create();
System.out.println(gson.toJson(bean));
}
}
class ExceptionSerializer implements JsonSerializer<Exception>
{
@Override
public JsonElement serialize(Exception src, Type typeOfSrc, JsonSerializationContext context)
{
JsonObject jsonObject = new JsonObject();
jsonObject.add("cause", new JsonPrimitive(String.valueOf(src.getCause())));
jsonObject.add("message", new JsonPrimitive(src.getMessage()));
return jsonObject;
}
}
class MyBean
{
public String data;
public Exception problem;
}
output:
{"data":"some data","problem":{"cause":"null","message":"Ack!"}}
For what it's worth, Jackson does not similarly choke when attempting to serialize the same data structure. Jackson serializes a MyBean
instance to JSON as follows.
{
"data":"some data",
"problem":
{
"cause":null,
"message":"Ack!",
"localizedMessage":"Ack!",
"stackTrace":
[
{
"className":"com.stackoverflow.q8151082.JacksonFoo",
"fileName":"JacksonFoo.java",
"lineNumber":11,
"methodName":"main",
"nativeMethod":false
}
]
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With