2011-11-16 42 views
9

我有一個包含一段數據和相關異常的對象。GSON an Java Throwable

Public class MyBean{ 
    Private String data; 
    Private Exception problem; 
. 
. 
. 
} 

當我嘗試GSON.toJSON(對象)它給了我一個循環引用抱怨的「問題」領域錯誤。

有沒有辦法讓GSON來處理這樣的對象?

+0

我嘗試使用org.apache.log4j.Logger字段序列化對象時遇到了同樣的問題。 –

回答

14

當試圖序列化原始問題中描述的數據結構時,Gson確實抱怨循環引用錯誤。

以下示例演示了這一點。

import com.google.gson.Gson; 

public class GsonFoo 
{ 
    public static void main(String[] args) 
    { 
    MyBean bean = new MyBean(); 
    bean.data = "some data"; 
    bean.problem = new RuntimeException("Ack!"); 

    System.out.println(new Gson().toJson(bean)); 
    } 
} 

class MyBean 
{ 
    public String data; 
    public Exception problem; 
} 

本示例導致以下來自Gson的異常和消息。

Exception in thread "main" java.lang.IllegalStateException: circular reference error 
    Offending field: cause 

    Offending object: preserveType: false, type: class java.lang.Throwable, obj: java.lang.RuntimeException: Ack! 
    at com.google.gson.CircularReferenceException.createDetailedException(CircularReferenceException.java:43) 
    at com.google.gson.JsonSerializationVisitor.visitObjectField(JsonSerializationVisitor.java:117) 
... 

當試圖像下面這樣簡單的事情時,Gson同樣ch聲。

System.out.println(new Gson().toJson(new RuntimeException("Ack!"))); 

Gson目前沒有配置可用於簡單地解決此問題。我建議在http://code.google.com/p/google-gson/issues/list處記錄一個問題。

如果必須序列化帶有Exception引用的對象,並且必須使用Gson,則必須實現Exception引用的自定義序列化處理。以下是一個這樣的例子。

import java.lang.reflect.Type; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonObject; 
import com.google.gson.JsonPrimitive; 
import com.google.gson.JsonSerializationContext; 
import com.google.gson.JsonSerializer; 

public class GsonFoo 
{ 
    public static void main(String[] args) 
    { 
    MyBean bean = new MyBean(); 
    bean.data = "some data"; 
    bean.problem = new RuntimeException("Ack!"); 

    GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(Exception.class, new ExceptionSerializer()); 
    Gson gson = gsonBuilder.create(); 

    System.out.println(gson.toJson(bean)); 
    } 
} 

class ExceptionSerializer implements JsonSerializer<Exception> 
{ 
    @Override 
    public JsonElement serialize(Exception src, Type typeOfSrc, JsonSerializationContext context) 
    { 
    JsonObject jsonObject = new JsonObject(); 
    jsonObject.add("cause", new JsonPrimitive(String.valueOf(src.getCause()))); 
    jsonObject.add("message", new JsonPrimitive(src.getMessage())); 
    return jsonObject; 
    } 
} 

class MyBean 
{ 
    public String data; 
    public Exception problem; 
} 

輸出:

{"data":"some data","problem":{"cause":"null","message":"Ack!"}} 

對於它的價值,Jackson不同樣試圖序列相同的數據結構時嗆。 Jackson如下將一個MyBean實例序列化爲JSON。

{ 
    "data":"some data", 
    "problem": 
    { 
    "cause":null, 
    "message":"Ack!", 
    "localizedMessage":"Ack!", 
    "stackTrace": 
    [ 
     { 
     "className":"com.stackoverflow.q8151082.JacksonFoo", 
     "fileName":"JacksonFoo.java", 
     "lineNumber":11, 
     "methodName":"main", 
     "nativeMethod":false 
     } 
    ] 
    } 
} 
+0

僅供參考,以下是有關Gson相關問題的鏈接:https://code.google.com/p/google-gson/issues/detail?id=469請對該問題進行明星排名,以便獲得更多關注。 – Simon

+0

我建議使用registerTypeHierarchyAdapter而不是registerTypeAdapter,因爲您可能想要爲所有Exception的子類型使用自定義序列化程序。 – prasopes

+0

這已在Gson v2.3.1中修復 – Behnil

0

GSON可以將其他自定義類作爲第一類的屬性處理,但是您是以這種方式使用它嗎?

gson.fromJson(yourResponse,MyBean.class) 

並且是您的自定義類的一個例外嗎?也許如果可以與java.lang.Exception衝突。

+0

Exception是一個持有的bean,是一個普通的java.lang.Exception。它抱怨Exception字段本身。 – Ben

+0

你可以在你的帖子中顯示Gson的「抱怨」嗎? –

2

我知道,這不是答案的具體問題(這是前2年以上回答正確) 但是:對於那些誰得到這個例外,在其他情況下

嘗試解析gson不知道解析的複雜字段時發生此錯誤。

,如果你需要這個領域在你的類,但不能解析的目的,你想從GSON分析排除,您可以:

  • @Expose註釋添加到所有的領域,你要分析,(像@Expose private Long id;
  • 聲明GSON對象是這樣的:

    GSON GSON =全新G 。sonBuilder()excludeFieldsWithoutExposeAnnotation()創建();

那就是幫助我

0

我也正面臨着同樣的問題在GSON版本2.2.2。在Gson版本2.6.1中,我沒有看到這個問題。