Gson thực sự phàn nàn về lỗi tham chiếu vòng tròn khi cố gắng tuần tự hóa cấu trúc dữ liệu như được mô tả trong câu hỏi gốc.
Ví dụ sau minh họa điểm này.
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;
}
Ví dụ này dẫn đến ngoại lệ và thông báo sau từ 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 tương tự chokes khi cố gắng đơn giản như sau.
System.out.println(new Gson().toJson(new RuntimeException("Ack!")));
Gson hiện không có cấu hình để giải quyết vấn đề này. Tôi khuyên bạn nên ghi lại sự cố tại số http://code.google.com/p/google-gson/issues/list.
Nếu một đối tượng có tham chiếu Exception
phải được tuần tự hóa và nếu phải sử dụng Gson, thì việc xử lý tuần tự hóa tùy chỉnh cho tham chiếu Exception
phải được triển khai. Sau đây là một ví dụ.
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;
}
đầu ra:
{"data":"some data","problem":{"cause":"null","message":"Ack!"}}
Đối với những gì nó có giá trị, Jackson không tương tự như nghẹt thở khi cố gắng serialize cấu trúc dữ liệu tương tự. Jackson serializes một ví dụ MyBean
đến JSON như sau.
{
"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
}
]
}
}
Tôi gặp phải sự cố tương tự khi cố gắng sắp xếp một đối tượng bằng trường org.apache.log4j.Logger. –