Ich möchte aus meinem Objekt einen JSON-String generieren:
Gson gson = new Gson();
String json = gson.toJson(item);
Jedes Mal, wenn ich dies versuche, wird folgende Fehlermeldung angezeigt:
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 referenzierten 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;
Irgendeine Idee, was diesen Fehler verursacht? Wie kann ich es reparieren?
JsonWriter.java:473)
, wie man die Grundursache des Gson-Stapelüberlaufs identifiziertAntworten:
Dieses Problem ist, dass Sie einen Zirkelverweis haben.
In der
BomModule
Klasse, auf die Sie sich beziehen:Dieser Selbstbezug
BomModule
, der GSON offensichtlich überhaupt nicht gefällt.Eine Problemumgehung besteht darin, die Module so einzustellen
null
, dass die rekursive Schleife vermieden wird. Auf diese Weise kann ich die StackOverFlow-Ausnahme vermeiden.Oder markieren Sie die Felder, die nicht im serialisierten JSON angezeigt werden sollen, mit dem
transient
Schlüsselwort, z.quelle
Ich hatte dieses Problem, als ich einen Log4J-Logger als Klasseneigenschaft hatte, wie zum Beispiel:
Dies kann gelöst werden, indem entweder der Logger erstellt
static
oder einfach in die eigentliche (n) Funktion (en) verschoben wird.quelle
Wenn Sie Realm verwenden und dieser Fehler auftritt und das Objekt, das den Fehler verursacht, RealmObject erweitert, vergessen Sie nicht
realm.copyFromRealm(myObject)
, eine Kopie ohne alle Realm-Bindungen zu erstellen, bevor Sie zur Serialisierung an GSON übergeben.Ich hatte es versäumt, dies nur für eines von vielen Objekten zu tun, die kopiert wurden. Es dauerte ewig, bis mir klar wurde, dass der Stack-Trace die Objektklasse / den Objekttyp nicht benennt. Das Problem wird durch einen Zirkelverweis verursacht, aber es ist ein Zirkelverweis irgendwo in der RealmObject-Basisklasse, nicht Ihre eigene Unterklasse, was das Erkennen erschwert!
quelle
Wie SLaks sagte, tritt StackOverflowError auf, wenn Sie einen Zirkelverweis in Ihrem Objekt haben.
Um dies zu beheben, können Sie TypeAdapter für Ihr Objekt verwenden.
Wenn Sie beispielsweise nur einen String aus Ihrem Objekt generieren müssen, können Sie einen Adapter wie den folgenden verwenden:
und registrieren Sie es so:
oder so, wenn Sie eine Schnittstelle haben und den Adapter für alle seine Unterklassen verwenden möchten:
quelle
Meine Antwort ist etwas spät, aber ich denke, diese Frage hat noch keine gute Lösung. Ich habe es ursprünglich hier gefunden .
Mit Gson können Sie die Felder markieren Sie tun möchten mit in json aufgenommen werden
@Expose
wie folgt aus :und erstellen Sie das gson-Objekt mit:
Rundschreiben, die Sie einfach nicht aussetzen. Das hat den Trick für mich getan!
quelle
Dieser Fehler tritt häufig auf, wenn Sie einen Logger in Ihrer Superklasse haben. Wie bereits von @Zar vorgeschlagen, können Sie static für Ihr Logger-Feld verwenden. Dies funktioniert jedoch auch:
PS wahrscheinlich wird es funktionieren und mit @Expose Annotation überprüfen Sie mehr dazu hier: https://stackoverflow.com/a/7811253/1766166
quelle
Ich habe das gleiche Problem. In meinem Fall war der Grund, dass der Konstruktor meiner serialisierten Klasse eine Kontextvariable wie folgt verwendet:
Wenn ich dieses Argument lösche, ist ein Fehler aufgetreten.
quelle
Edit: Sorry für mein schlechtes, das ist meine erste Antwort. Vielen Dank für Ihre Ratschläge.
Ich erstelle meinen eigenen Json Converter
Die Hauptlösung, die ich verwendet habe, besteht darin, für jede Objektreferenz einen übergeordneten Objektsatz zu erstellen. Wenn eine Unterreferenz auf ein vorhandenes übergeordnetes Objekt verweist, wird sie verworfen. Dann kombiniere ich mit einer zusätzlichen Lösung, die die Referenzzeit begrenzt, um eine Endlosschleife in der bidirektionalen Beziehung zwischen Entitäten zu vermeiden.
Meine Beschreibung ist nicht so gut, hoffe es hilft euch.
Dies ist mein erster Beitrag zur Java-Community (Lösung Ihres Problems). Sie können es überprüfen;) Es gibt eine README.md-Datei https://github.com/trannamtrung1st/TSON
quelle
In Android stellte sich heraus, dass der Gson-Stack-Überlauf die Deklaration eines Handlers war. Verschob es in eine Klasse, die nicht deserialisiert wird.
Auf Empfehlung von Zar habe ich den Handler statisch gemacht, als dies in einem anderen Codeabschnitt geschah. Es hat auch funktioniert, den Handler statisch zu machen.
quelle
BomItem
verweist aufBOMModule
(Collection<BomModule> modules
) undBOMModule
verweist aufBOMItem
(Collection<BomItem> items
). Die Gson-Bibliothek mag keine Zirkelverweise. Entfernen Sie diese zirkuläre Abhängigkeit aus Ihrer Klasse. Auch ich hatte in der Vergangenheit mit gson lib das gleiche Problem.quelle
Ich hatte dieses Problem bei mir, als ich sagte:
in meinem Objekt ... was nach ungefähr einer Stunde Debuggen vollkommen Sinn machte!
quelle
Für Android-Benutzer können Sie a
Bundle
aufgrund einer Selbstreferenz zurBundle
Verursachung von a nicht serialisierenStackOverflowError
.Um ein Bundle zu serialisieren, registrieren Sie a
BundleTypeAdapterFactory
.quelle
Vermeiden Sie unnötige Problemumgehungen, z. B. das Setzen von Werten auf Null oder das Übertragen von Feldern. Der richtige Weg, dies zu tun, besteht darin, eines der Felder mit @Expose zu kommentieren und dann Gson anzuweisen, nur die Felder mit der Annotation zu serialisieren:
quelle
Ich hatte ein ähnliches Problem, bei dem die Klasse eine InputStream-Variable hatte, die ich nicht wirklich beibehalten musste. Daher wurde das Problem durch Ändern in Transient behoben.
quelle
Nach einiger Zeit des Kampfes mit diesem Problem glaube ich, dass ich eine Lösung habe. Das Problem liegt in ungelösten bidirektionalen Verbindungen und in der Darstellung von Verbindungen, wenn diese serialisiert werden. Die Möglichkeit, dieses Verhalten zu beheben, besteht darin, zu "erklären",
gson
wie Objekte serialisiert werden sollen. Zu diesem Zweck verwenden wirAdapters
.Mithilfe von können
Adapters
wir feststellen,gson
wie jede Eigenschaft aus IhrerEntity
Klasse serialisiert wird und welche Eigenschaften serialisiert werden sollen.Lassen Sie
Foo
undBar
zwei Einheiten, in denenFoo
hatOneToMany
gegenüberBar
undBar
hatManyToOne
gegenüberFoo
. Wir definieren denBar
Adapter so, dass beimgson
Serialisieren keineBar
SerialisierungFoo
aus Sicht derBar
zyklischen Referenzierung möglich ist.Hier
foo_id
wird eineFoo
Entität dargestellt , die serialisiert werden würde und die unser zyklisches Referenzierungsproblem verursachen würde. Wenn wir jetzt den Adapter verwenden,Foo
wird er nicht erneut serialisiert, sondernBar
nur seine ID wird übernommen und eingegebenJSON
. Jetzt haben wir einenBar
Adapter und können ihn zum Serialisieren verwendenFoo
. Hier ist die Idee:Eine weitere Sache zu klären,
foo_id
ist nicht obligatorisch und kann übersprungen werden. Der Zweck des Adapters in diesem Beispiel ist die Serialisierung.Bar
Durch das Setzen habenfoo_id
wir gezeigt, dassBar
das auslösen kann,ManyToOne
ohne dassFoo
esOneToMany
erneut ausgelöst wird ...Die Antwort basiert auf persönlicher Erfahrung. Sie können daher gerne Kommentare abgeben, mir das Gegenteil beweisen, Fehler beheben oder die Antwort erweitern. Trotzdem hoffe ich, dass jemand diese Antwort nützlich findet.
quelle