GSON是Java Throwable

Ben*_*Ben 10 java exception gson

我有一个包含一段数据和相关异常的对象.

Public class MyBean{
  Private String data;
  Private Exception problem;
.
.
.
}
Run Code Online (Sandbox Code Playgroud)

当我尝试GSON.toJSON(对象)时,它给我一个循环引用错误抱怨"问题"字段.

有没有办法让GSON处理这些对象?

Pro*_*uce 18

在尝试序列化数据结构时,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;
}
Run Code Online (Sandbox Code Playgroud)

此示例导致以下异常和来自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)
...
Run Code Online (Sandbox Code Playgroud)

在尝试如下简单的事情时,Gson同样会窒息.

System.out.println(new Gson().toJson(new RuntimeException("Ack!")));
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

{"data":"some data","problem":{"cause":"null","message":"Ack!"}}
Run Code Online (Sandbox Code Playgroud)

对于它的价值,杰克逊在尝试序列化相同的数据结构时不会同样窒息.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
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)