2012-04-18 6 views
50

Stackoverflow Ich möchte einen JSON String von meinem Objekt erzeugen:gson.toJson() throws

Gson gson = new Gson(); 
String json = gson.toJson(item); 

Jedesmal, wenn ich versuchen, dies zu tun, bekomme ich diesen Fehler:

14:46:40,236 ERROR [[BomItemToJSON]] Servlet.service() for servlet BomItemToJSON threw exception 
java.lang.StackOverflowError 
    at com.google.gson.stream.JsonWriter.string(JsonWriter.java:473) 
    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:347) 
    at com.google.gson.stream.JsonWriter.value(JsonWriter.java:440) 
    at com.google.gson.internal.bind.TypeAdapters$7.write(TypeAdapters.java:235) 
    at com.google.gson.internal.bind.TypeAdapters$7.write(TypeAdapters.java:220) 
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:200) 
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60) 
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:843) 

Dies sind die Attribute meiner BomItem Klasse:

private int itemId; 
private Collection<BomModule> modules; 
private boolean deprecated; 
private String partNumber; 
private String description; //LOB 
private int quantity; 
private String unitPriceDollar; 
private String unitPriceEuro; 
private String discount; 
private String totalDollar; 
private String totalEuro; 
private String itemClass; 
private String itemType; 
private String vendor; 
private Calendar listPriceDate; 
private String unitWeight; 
private String unitAveragePower; 
private String unitMaxHeatDissipation; 
private String unitRackSpace; 

Attribute meiner beziehen rener BomModule Klasse:

private int moduleId; 
private String moduleName; 
private boolean isRootModule; 
private Collection<BomModule> parentModules; 
private Collection<BomModule> subModules; 
private Collection<BomItem> items; 
private int quantity; 

Jede Idee, was diesen Fehler verursacht? Wie kann ich es reparieren?

+0

Konnte passieren, wenn Sie eine Objektinstanz innerhalb des Gons in sich selbst setzen. –

+0

Die Ausnahmebedingung löscht die Ursache und startet das Protokoll mit 'JsonWriter.java:473' ', wie identifiziert man die Ursache des Gson stackoverflow – Siddharth

Antwort

52

Das würde wahrscheinlich passieren, wenn Sie eine zirkuläre Referenz haben.

Bezieht sich BomModule auf Ihr übergeordnetes Objekt?

+0

Ja ein BomModule-Objekt kann Teil eines anderen BomModule-Objekts sein. – doonot

+0

Aber ist das ein Problem? "Collection Module" ist nur eine Sammlung, und ich denke, dass Gson in der Lage sein sollte, ein einfaches Array daraus zu machen? – doonot

+0

@dooonot: Bezieht sich eines der Objekte in der Sammlung auf das übergeordnete Objekt? – SLaks

21

hatte ich dieses Problem, wenn ich einen Log4J Logger als Klasse Eigenschaft hatte, wie zum Beispiel:

private Logger logger = Logger.getLogger(Foo.class); 

Dies kann entweder durch Herstellung des Loggers static oder einfach, indem sie in die eigentliche Funktion bewegt gelöst werden (s).

+4

Absolut toller Fang. Das selbst Bezug auf die Klasse offensichtlich nicht von GSON überhaupt gemocht.Ersparte mir eine Menge Kopfschmerzen ! +1 – christopher

+1

ein anderer Weg, um es zu lösen, ist durch Hinzufügen von Transienten-Modifikator zum Feld – gawi

0

In Android entpuppte sich der gson stack overflow als Deklaration eines Handlers. Es wurde in eine Klasse verschoben, die nicht deserialisiert wird.

Basierend auf Zars Empfehlung, habe ich den Handler statisch gemacht, als dies in einem anderen Codeabschnitt passiert ist. Die statische Funktionsweise des Handlers wurde ebenfalls verbessert.

10

Wie SLaks sagte StackOverflowError passieren, wenn Sie Zirkelbezug in Ihrem Objekt haben.

Um es zu beheben, könnten Sie TypeAdapter für Ihr Objekt verwenden.

Zum Beispiel, wenn Sie nur String von Ihrem Objekt erzeugen benötigen könnten Sie Adapter wie folgt verwenden:

class MyTypeAdapter<T> extends TypeAdapter<T> { 
    public T read(JsonReader reader) throws IOException { 
     return null; 
    } 

    public void write(JsonWriter writer, T obj) throws IOException { 
     if (obj == null) { 
      writer.nullValue(); 
      return; 
     } 
     writer.value(obj.toString()); 
    } 
} 

und registrieren Sie es wie folgt aus:

Gson gson = new GsonBuilder() 
       .registerTypeAdapter(BomItem.class, new MyTypeAdapter<BomItem>()) 
       .create(); 

oder wie diese, wenn Sie Schnittstelle und möchte Adapter für alle seine Unterklassen verwenden:

Gson gson = new GsonBuilder() 
       .registerTypeHierarchyAdapter(BomItemInterface.class, new MyTypeAdapter<BomItemInterface>()) 
       .create(); 
1

Ich habe das gleiche Problem. In meinem Fall war der Grund, dass Konstruktor meiner serialisierte Klasse nehmen Kontextvariable, wie folgt aus:

public MetaInfo(Context context) 

Als ich dieses Argument löschen, Fehler gegangen ist.

public MetaInfo() 
+1

Ich stieß auf dieses Problem bei der Übergabe von Service Objektreferenz als Kontext. Fix war, die Kontextvariable in der Klasse, die gson.toJson (this) verwendet, statisch zu machen. – user802467

+0

@ user802467 meinst du android service? – Preetam

2

Dieser Fehler tritt häufig auf, wenn Sie einen Logger in Ihrer Superklasse haben.Wie @Zar vor vorgeschlagen, können Sie statische für Ihren Logger Feld verwenden, aber das funktioniert auch:

protected final transient Logger logger = Logger.getLogger(this.getClass()); 

P. S. wahrscheinlich wird es funktionieren und mit @Expose Anmerkung mehr dazu hier überprüfen: https://stackoverflow.com/a/7811253/1766166

0

BomItem zu BOMModule bezieht (Collection<BomModule> modules) und BOMModule bezieht sich auf BOMItem (Collection<BomItem> items). Die Gson-Bibliothek mag keine kreisförmigen Referenzen. Entfernen Sie diese zirkuläre Abhängigkeit von Ihrer Klasse. Auch ich hatte in der Vergangenheit mit gson lib dasselbe Problem konfrontiert.

7

Wenn Sie Realm verwenden und diese Fehlermeldung angezeigt, und das Objekt sich die Mühe geben sich RealmObject, vergessen Sie nicht realm.copyFromRealm(myObject) zu tun, um eine Kopie ohne alle Realm Bindungen zu schaffen, bevor sie durch für die Serialisierung zu Gson vorbei.

Ich habe es vermisst, dies nur für eines unter einer Reihe von Objekten zu tun, die kopiert werden ... dauerte mir alters zu erkennen, wie der Stack-Trace nicht die Objektklasse/Typ nennt. Das Problem ist, dass das Problem durch einen Zirkelverweis verursacht wird, aber es ist ein Zirkelverweis irgendwo in der RealmObject-Basisklasse, nicht eine eigene Unterklasse, was es schwieriger macht, sie zu erkennen!

+0

Das stimmt!In meinem Fall ändere meine Objektliste direkt von Realm auf ArrayList copyList = new ArrayList <>(); für (Bild Bild: Bilder) { copyList.add (realm.copyFromRealm (Bild)); } –

4

Meine Antwort ist ein bisschen spät, aber ich denke, diese Frage hat noch keine gute Lösung. Ich fand es ursprünglich here.

Mit Gson können Sie die Felder markieren Sie wollen tun mit @Expose in json aufgenommen werden und die Gson Objekt erstellen mit:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); 

, die den Trick für mich getan hat!