Gson se queja de un error de referencia circular al intentar serializar una estructura de datos como se describe en la pregunta original.
El siguiente ejemplo demuestra este punto.
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;
}
Este ejemplo da como resultado la siguiente excepción y mensaje de 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 se atraganta al intentar algo tan simple como el siguiente.
System.out.println(new Gson().toJson(new RuntimeException("Ack!")));
Gson no tiene actualmente una configuración disponible para resolver simplemente este problema. Recomiendo iniciar sesión en el http://code.google.com/p/google-gson/issues/list.
Si un objeto con una referencia Exception
debe ser serializado y si se debe usar Gson, entonces debe implementarse el procesamiento de serialización personalizado para la referencia Exception
. El siguiente es uno de esos ejemplos.
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;
}
de salida:
{"data":"some data","problem":{"cause":"null","message":"Ack!"}}
Por lo que vale la pena, Jackson no ahogar de manera similar al intentar serializar la misma estructura de datos. Jackson serializa una instancia MyBean
a JSON de la siguiente manera.
{
"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
}
]
}
}
Tuve el mismo problema al intentar serializar un objeto con un campo org.apache.log4j.Logger. –