2011-11-16 37 views
9

Tengo un objeto que contiene un fragmento de datos y una excepción asociada.GSON y Java Throwable

Public class MyBean{ 
    Private String data; 
    Private Exception problem; 
. 
. 
. 
} 

Cuando intento GSON.toJSON (objeto) Me da una referencias circulares se quejan error sobre el campo "problema".

¿Hay alguna forma de que GSON maneje tales objetos?

+0

Tuve el mismo problema al intentar serializar un objeto con un campo org.apache.log4j.Logger. –

Respuesta

14

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 
     } 
    ] 
    } 
} 
+0

Solo como referencia, aquí hay un enlace al problema de Gson correspondiente: https://code.google.com/p/google-gson/issues/detail?id=469 Haga clic en el tema para que reciba más atención. – Simon

+0

Sugiero usar registerTypeHierarchyAdapter en lugar de registerTypeAdapter ya que probablemente quiera usar el serializador personalizado para todos los subtipos de Exception. – prasopes

+0

Esto se ha corregido en Gson v2.3.1 – Behnil

0

GSON puede manejar otras clases personalizadas como atributos de su primera clase, pero ¿lo está utilizando de esa manera?

gson.fromJson(yourResponse,MyBean.class) 

y es una excepción de su clase personalizada? Tal vez si puede estar en conflicto con java.lang.Exception.

+0

la excepción que se guarda dentro del bean es una java.lang.Exception simple. se está quejando sobre el campo Exception en sí mismo. – Ben

+0

¿Puedes mostrar en tu publicación el "Quejarse" de Gson? –

2

Yo sé que no es la respuesta a la pregunta específica (que fue contestada correctamente antes de más de 2 años) Pero:

para aquellos que reciben esta excepción, en otros casos:

este error ocurre al intentar analizar un campo complicado que gson no sabe analizar.

si necesita este campo en su clase, pero no para el análisis objetivo y quiere excluirlo del análisis GSON, puede:

  • añadir la anotación @Expose a todos los campos que querer analizar, (algo así como @Expose private Long id;)
  • declaran el objeto Gson así:

    Gson GSON = nuevo G sonBuilder(). excludeFieldsWithoutExposeAnnotation(). create();

eso es lo que me ayudó

0

también estaba enfrentando el mismo problema en Gson la versión 2.2.2. En la versión 2.6.1 de Gson, no veo este problema.