2012-04-18 195 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(); 

這奏效了我!

相關問題