2011-11-16 3 views
9

Ho un oggetto che contiene un pezzo di dati e un'eccezione associata.GSON a Java Throwable

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

Quando provo a GSON.toJSON (oggetto) mi dà un riferimenti circolari errore lamentano il campo "problema".

C'è un modo per GSON per gestire tali oggetti?

+0

Ho riscontrato lo stesso problema durante il tentativo di serializzare un oggetto con un campo org.apache.log4j.Logger. –

risposta

14

Gson effettivamente si lamenta di un errore di riferimento circolare durante il tentativo di serializzare una struttura dati come descritto nella domanda originale.

L'esempio seguente dimostra questo 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; 
} 

Questo esempio genera la seguente eccezione e messaggio da 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 soffoca allo stesso modo quando si tenta qualcosa di semplice come il seguente.

System.out.println(new Gson().toJson(new RuntimeException("Ack!"))); 

Gson al momento non dispone di una configurazione disponibile per risolvere semplicemente questo problema. Raccomando di registrare un problema allo http://code.google.com/p/google-gson/issues/list.

Se un oggetto con un riferimento Exception deve essere serializzato e se Gson deve essere utilizzato, è necessario implementare l'elaborazione di serializzazione personalizzata per il riferimento Exception. Di seguito è riportato un esempio.

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; 
} 

uscita:

{"data":"some data","problem":{"cause":"null","message":"Ack!"}} 

Per quel che vale, Jackson non soffocare in modo simile quando si tenta di serializzare la stessa struttura di dati. Jackson serializza un'istanza MyBean in JSON come segue.

{ 
    "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 per riferimento, ecco un collegamento al relativo problema Gson: https://code.google.com/p/google-gson/issues/detail?id=469 Si prega di inserire il problema in modo che riceva maggiore attenzione. – Simon

+0

Suggerisco di utilizzare registerTypeHierarchyAdapter invece di registerTypeAdapter poiché probabilmente si desidera utilizzare il serializzatore personalizzato per tutti i sottotipi di Exception. – prasopes

+0

Questo problema è stato corretto in Gson v2.3.1 – Behnil

0

GSON può gestire altre classi personalizzate come attributi della prima classe, ma la stai usando in questo modo?

gson.fromJson(yourResponse,MyBean.class) 

ed è un'eccezione uno della classe personalizzata? Forse se può essere in conflitto con java.lang.Exception.

+0

l'eccezione è una trattenuta all'interno del bean è una semplice java.lang.Exception. si lamenta del campo Eccezione stesso. – Ben

+0

Puoi mostrare nel tuo post il "Reclamo" di Gson? –

2

So che non è la risposta alla domanda specifica (che è stato risposto in modo corretto davanti a più di 2 anni) Ma:

per chi ottiene questa eccezione in altri casi:

questo errore si verifica durante il tentativo di analizzare il campo complicato che gson non sa analizzare.

se avete bisogno di questo campo nella classe, ma non per l'analisi scopo e che si desidera escludere dalla analisi GSON, è possibile:

  • aggiungere il @Expose annotazioni a tutti i campi che si vuole analizzare, (qualcosa come @Expose private Long id;)
  • dichiarare l'oggetto GSON in questo modo:

    GSON GSON = new G . SonBuilder() excludeFieldsWithoutExposeAnnotation() create().;

questo è quello che mi ha aiutato

0

anch'io stavo affrontando lo stesso problema in GSON versione 2.2.2. In Gson versione 2.6.1 non vedo questo problema.