gson.toJson () lance StackOverflowError

Je voudrais générer une chaîne JSON à partir de mon object:

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

Chaque fois que j’essaie de faire cela, j’obtiens cette erreur:

 14:46:40,236 ERROR [[BomItemToJSON]] Servlet.service() for servlet BomItemToJSON threw exception java.lang.StackOverflowError at com.google.gson.stream.JsonWriter.ssortingng(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) 

Ce sont les atsortingbuts de ma classe BomItem :

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

Atsortingbuts de ma classe BomModule référencée:

 private int moduleId; private Ssortingng moduleName; private boolean isRootModule; private Collection parentModules; private Collection subModules; private Collection items; private int quantity; 

Toute idée de la cause de cette erreur? Comment puis-je le réparer?

Ce problème est que vous avez une référence circulaire.

Dans la classe BomModule , vous faites référence à:

 private Collection parentModules; private Collection subModules; 

Cette référence à BomModule , évidemment, n’aime pas du tout GSON.

Une solution de contournement consiste à définir les modules sur null pour éviter le bouclage récursif. De cette façon, je peux éviter l’exception StackOverFlow-Exception.

 item.setModules(null); 

Ou marquez les champs que vous ne voulez pas afficher dans json sérialisé en utilisant le mot-clé transient , par exemple:

 private transient Collection parentModules; private transient Collection subModules; 

J’ai eu ce problème lorsque j’avais un enregistreur Log4J en tant que propriété de classe, tel que:

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

Cela peut être résolu en rendant l’enregistreur static ou en le déplaçant simplement dans la ou les fonctions réelles.

Comme SLaks dit StackOverflowError se produit si vous avez une référence circulaire dans votre object.

Pour résoudre ce problème, vous pouvez utiliser TypeAdapter pour votre object.

Par exemple, si vous avez seulement besoin de générer de la chaîne à partir de votre object, vous pouvez utiliser l’adaptateur comme ceci:

 class MyTypeAdapter extends TypeAdapter { 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.toSsortingng()); } } 

et enregistrez-le comme ceci:

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

ou comme ça, si vous avez une interface et que vous voulez utiliser un adaptateur pour toutes ses sous-classes:

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

Si vous utilisez Realm et que vous obtenez cette erreur, et que l’object donnant le problème étend RealmObject, n’oubliez pas de faire realm.copyFromRealm(myObject) pour créer une copie sans toutes les liaisons Realm avant de passer à GSON pour la sérialisation.

Je n’avais pas réussi à le faire pour un seul object parmi tant d’autres à copier … il m’a fallu des années pour réaliser que la trace de la stack ne nommait pas la classe / le type d’object. En fait, le problème est dû à une référence circulaire, mais il s’agit d’une référence circulaire quelque part dans la classe de base RealmObject, pas dans votre propre sous-classe, ce qui rend la tâche plus difficile à repérer!

Ma réponse est un peu en retard, mais je pense que cette question n’a pas encore une bonne solution. Je l’ai trouvé à l’origine ici .

Avec Gson, vous pouvez marquer les champs que vous voulez inclure dans json avec @Expose comme ceci:

 @Expose Ssortingng mySsortingng; // will be serialized as mySsortingng 

et créez l’object gson avec:

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

Les références circulaires que vous n’exposez pas . Cela a fait le tour pour moi!

Cette erreur est courante lorsque vous avez un enregistreur dans votre super classe. Comme @Zar l’a suggéré précédemment, vous pouvez utiliser statique pour votre champ d’enregistreur, mais cela fonctionne également:

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

PS probablement cela va fonctionner et avec l’annotation @Expose vérifier plus à ce sujet ici: https://stackoverflow.com/a/7811253/1766166

J’ai le même problème. Dans mon cas, la raison était que le constructeur de ma classe sérialisée prenait une variable de contexte, comme ceci:

 public MetaInfo(Context context) 

Lorsque je supprime cet argument, l’erreur est partie.

 public MetaInfo() 

Dans Android, le débordement de la stack gson s’est avéré être la déclaration d’un gestionnaire. Je l’ai déplacé dans une classe qui n’est pas désérialisée.

Sur la base de la recommandation de Zar, j’ai rendu le gestionnaire statique lorsque cela se produisait dans une autre section de code. Le statique du gestionnaire a également fonctionné.

BomItem fait référence aux BOMModule ( Collection modules ) et BOMModule à BOMItem (éléments Collection items ). La bibliothèque Gson n’aime pas les références circulaires. Supprimez cette dépendance circulaire de votre classe. J’avais moi aussi fait face au même problème avec gson lib.

J’ai eu ce problème pour moi quand j’ai mis:

 Logger logger = Logger.getLogger( this.getClass().getName() ); 

dans mon object … qui était parfaitement logique après une heure de débogage!

Edit: Désolé pour mon mal, c’est ma première réponse. Merci pour vos conseils.

Je crée mon propre convertisseur Json

La principale solution que j’ai utilisée consiste à créer un ensemble d’objects parents pour chaque référence d’object. Si une sous-référence pointe vers un object parent existant, elle sera rejetée. Ensuite, je combine avec une solution supplémentaire, en limitant le temps de référence pour éviter une boucle infinitive dans une relation bidirectionnelle entre entités.

Ma description n’est pas trop bonne, j’espère que cela vous aidera les gars.

Ceci est ma première consortingbution à la communauté Java (solution à votre problème). Vous pouvez le vérifier;) Il existe un fichier README.md https://github.com/trannamtrung1st/TSON