2012-04-18 191 views
50

我想从我的对象生成一个JSON字符串:gson.toJson()中抛出StackOverflowError

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

每次我尝试这样做,我得到这个错误:

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) 

这些都是我BomItem类的属性:我指

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; 

属性enced BomModule类:

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

任何想法是什么原因导致这个错误?我该如何解决它?

+0

如果你把一个对象实例放在gson里面的某个地方,可能会发生。 – 2015-11-24 10:12:18

+0

异常失去的根本原因开始日志与'JsonWriter.java:473)',如何确定根本原因的Gson stackoverflow – Siddharth 2017-06-03 11:40:37

回答

52

如果您有循环引用,可能会发生这种情况。

BomModule是否引用您的父对象?

+0

是一个BomModule对象可以是另一个BomModule对象的一部分。 – doonot 2012-04-18 13:06:18

+0

但这是一个问题吗? 'Collection modules'只是一个集合,我认为gson应该能够制作一个简单的数组呢? – doonot 2012-04-18 13:11:51

+0

@dooonot:集合中的任何对象是否引用其父对象? – SLaks 2012-04-18 13:15:59

21

我有这个问题时,我有一个Log4J的记录作为一个阶级属性,如:

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

这可以通过来解决移动它变成实际的功能使得记录static或者干脆(S )。

+4

绝对好的接受,自动引用该类显然不被GSON所喜欢,为我节省了很多头痛!+1 – christopher 2014-11-19 20:54:39

+1

解决它的另一种方法,就是通过在字段中加入瞬态修饰符 – gawi 2016-11-17 16:03:06

0

在Android中,gson堆栈溢出原来是Handler的声明。将其移动到未被反序列化的类。

根据Zar的建议,当这种情况发生在另一段代码中时,我使得处理程序是静态的。使处理程序静态工作。

10

由于SLaks表示StackOverflowError发生,如果你有对象的循环引用。

要解决这个问题,你可以使用TypeAdapter作为你的对象。

例如,如果你只需要生成你的对象的字符串,您可以使用适配器这样的:

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

像这样注册它:

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

或类似这样的,如果你有接口并希望使用适配器,用于其所有子类:

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

我有同样的问题。在我的情况的原因,是我的序列化类取上下文变量的这个构造,像这样:

public MetaInfo(Context context) 

当我删除这个说法,错误已经一去不复返了。

public MetaInfo() 
+1

我在通过服务时遇到了这个问题对象引用作为上下文。修正是在使用gson.toJson(this)的类中使上下文变量为静态。 – user802467 2014-11-04 23:22:25

+0

@ user802467你的意思是android服务? – Preetam 2016-05-02 07:43:34

2

当你在超类中有一个记录器时,这个错误很常见。作为@Zar之前的建议,您可以使用静态为您记录仪领域,而且这也适用:

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

附:也许它会工作,并与@expose注释检查更多关于此这里:https://stackoverflow.com/a/7811253/1766166

0

BomItemBOMModuleCollection<BomModule> modules),并BOMModuleBOMItemCollection<BomItem> items)。 Gson库不喜欢循环引用。从你的类中移除这个循环依赖。在过去,我也使用gson lib面临同样的问题。

7

如果您使用Realm并且出现此错误,并且出现故障的对象扩展了RealmObject,则在传递到GSON进行序列化之前,请不要忘记执行realm.copyFromRealm(myObject)以创建没有所有Realm绑定的副本。

我错过了为一对被复制的对象中的一个做这个......花了我很长时间才意识到,因为堆栈跟踪没有命名对象类/类型。问题是,这个问题是由循环引用引起的,但是它是RealmObject基类中某处的循环引用,而不是您自己的子类,这使得更难以发现!

+0

这是正确的!在我的情况下,将我的对象列表直接从领域查询到ArrayList copyList = new ArrayList <>(); (图片图片:图片){ copyList.add(realm.copyFromRealm(image)); } – 2017-05-25 20:11:04

4

我的答案有点晚了,但我认为这个问题还没有一个好的解决方案。我发现它最初是here

随着GSON你可以标记你要包含在JSON与@Expose领域,并创建GSON对象:

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

这奏效了我!

相关问题