2012-04-18 25 views
50

me gustaría generar una cadena JSON de mi objeto:gson.toJson() lanza StackOverflowError

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

Cada vez que intento hacer esto, me sale este error:

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) 

Son los atributos de mi BomItem clase:

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; 

atributos de mi referirse mentado BomModule clase:

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

Cualquier idea de lo que hace que este error? ¿Cómo puedo arreglarlo?

+0

Podría suceder si coloca una instancia de objeto dentro de sí misma en algún lugar dentro del servidor. –

+0

La excepción pierde la causa raíz e inicia el registro con 'JsonWriter.java:473)', cómo identifica la causa raíz del Gson stackoverflow – Siddharth

Respuesta

52

Eso probablemente sucedería si tiene una referencia circular.

¿BomModule hace referencia a su objeto principal?

+0

Sí, un objeto BomModule puede ser parte de otro objeto BomModule. – doonot

+0

¿Pero es eso un problema? 'Colección modules' es solo una colección, ¿y creo que Gson debería ser capaz de crear una matriz simple? – doonot

+0

@dooonot: ¿Alguno de los objetos en la colección hace referencia a su objeto principal? – SLaks

21

tuve este problema cuando tuve un registrador Log4J como propiedad de clase, tales como:

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

Esto se puede resolver ya sea haciendo el registrador static o simplemente moviéndolo en la función real (s)

+4

Absolutamente gran atrapamiento. Esa auto referencia a la clase obviamente no le gustaba GSON en absoluto. Me salvó un montón de dolores de cabeza ! +1 – christopher

+1

Otra forma de resolverlo es agregar un modificador transitorio al campo – gawi

0

En Android, gson stack overflow resultó ser la declaración de un controlador. Lo movió a una clase que no se está deserializando.

Basado en la recomendación de Zar, hice el controlador estático cuando esto sucedió en otra sección del código. Hacer el controlador estático funcionó también.

10

Como dijo SLaks StackOverflowError sucede si tiene una referencia circular en su objeto.

Para solucionarlo, puede usar TypeAdapter para su objeto.

Por ejemplo, si sólo necesita generar cuerdas de su objeto que podría utilizar adaptador de la siguiente manera:

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

y registrarlo como esto:

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

o así, si usted tiene interfaz y quiere utilizar el adaptador para todas sus subclases:

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

Tengo el mismo problema. En mi caso, la razón fue que el constructor de mi variable de contexto toma la clase serializada, así:

public MetaInfo(Context context) 

Al eliminar este argumento, el error ha desaparecido.

public MetaInfo() 
+1

Me encontré con este problema al pasar el servicio referencia de objeto como contexto. La solución consistía en hacer que la variable de contexto estuviera estática en la clase que usa gson.toJson (esto). – user802467

+0

@ user802467 ¿te refieres al servicio de Android? – Preetam

2

Este error es común cuando tiene un registrador en su súper clase.Como @Zar sugirió antes, puede utilizar estática para su campo de registrador, pero esto también funciona:

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

P. S. Probablemente va a trabajar y con la anotación @Expose comprobar más sobre esto aquí: https://stackoverflow.com/a/7811253/1766166

0

BomItem se refiere a BOMModule (Collection<BomModule> modules), y se refiere a BOMModuleBOMItem (Collection<BomItem> items). A la biblioteca Gson no le gustan las referencias circulares. Elimina esta dependencia circular de tu clase. Yo también había tenido el mismo problema en el pasado con gson lib.

7

Si está utilizando Realm y obtiene este error, y el objeto que causa el problema extiende RealmObject, no olvide hacer realm.copyFromRealm(myObject) para crear una copia sin todos los enlaces Realm antes de pasar a GSON para la serialización.

Eché de menos hacer esto solo por uno de los objetos que se están copiando ... me llevó años darme cuenta, ya que el seguimiento de la pila no nombra la clase/tipo de objeto. La cuestión es que el problema está causado por una referencia circular, pero es una referencia circular en algún lugar de la clase base RealmObject, no su propia subclase, ¡lo que hace que sea más difícil de detectar!

+0

¡Eso es correcto!En mi caso, cambie mi lista de objetos consultada directamente desde el reino a ArrayList copyList = new ArrayList <>(); for (Imagen de imagen: imágenes) { copyList.add (realm.copyFromRealm (image)); } –

4

Mi respuesta es un poco tarde, pero creo que esta pregunta aún no tiene una buena solución. Lo encontré originalmente here.

Con Gson puede marcar los campos que hacen quieren ser incluidos en JSON con @Expose y crear el objeto GSON con:

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

Que hizo el truco para mí!

Cuestiones relacionadas