仅序列化编译时信息

时间:2019-03-28 09:54:34

标签: java jackson

序列化Java对象时,由于它利用了反射,因此Jackson会在其运行时表示中序列化该对象。

我有以下课程:

@lombok.AllArgsConstructor
@lombokGetter
class ErrorInformation {

   private final Exception exception;
}

final ErrorInformation errorInfo = new ErrorInformation(new IllegalArgumentException("foo"));

Jackson不仅序列化了Exception,实际上还序列化了IllegalArgumentException中的所有字段-产生了不可控制的后果,例如循环引用(请参见mostSpecificCause中的org.springframework.web.client.HttpServerErrorException)。 / p>

我怎么能告诉杰克逊实际上只序列化Exception的信息,而不考虑实际的运行时类型,就像您希望从像Java这样的静态类型化语言中期望的那样?

2 个答案:

答案 0 :(得分:3)

Jackson默认情况下序列化给定getters中的所有POJO方法。如果我们要序列化3-rd party类,则需要注意周期和其他问题。为此,我们可以使用MixIn feature。我们需要定义所有NestedRuntimeException异常,我们要忽略getMostSpecificCause方法。

interface NestedRuntimeExceptionMixIn {

    @JsonIgnore
    Throwable getMostSpecificCause();
}

用法示例:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.core.NestedRuntimeException;
import org.springframework.http.HttpStatus;
import org.springframework.web.client.HttpServerErrorException;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        HttpServerErrorException exception = new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "error");
        ErrorInformation ei = new ErrorInformation(exception);

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.addMixIn(NestedRuntimeException.class, NestedRuntimeExceptionMixIn.class);

        System.out.println(mapper.writeValueAsString(ei));
    }
}

打印:

{
  "exception" : {
    "cause" : null,
    "stackTrace" : [ {
      "methodName" : "main",
      "fileName" : "JsonApp.java",
      "lineNumber" : 13,
      "className" : "JsonApp",
      "nativeMethod" : false
    } ],
    "rawStatusCode" : 500,
    "statusText" : "error",
    "responseHeaders" : null,
    "statusCode" : "INTERNAL_SERVER_ERROR",
    "responseBodyAsByteArray" : "",
    "responseBodyAsString" : "",
    "message" : "500 error",
    "rootCause" : null,
    "localizedMessage" : "500 error",
    "suppressed" : [ ]
  }
}

答案 1 :(得分:2)

由于我们无法更改IllegalArgumentException类的逻辑,因此可以在ErrorInformation类中创建其他实例字段,并在其中填充要序列化的信息,并将exception变量标记为{ {1}}

例如假设您要保存错误消息信息。因此,创建一个transient字段,例如String,并在构造函数中填充错误消息信息。下面是示例代码。

errorMessage

反序列化时,您可以使用此错误消息信息来创建已序列化的异常对象的相似(不相同)实例