2011-11-16 62 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中,我没有看到这个问题。