【问题标题】:Stackoverflow exception when trying to use custom JsonSerializer (Jackson)尝试使用自定义 JsonSerializer (Jackson) 时出现 Stackoverflow 异常
【发布时间】:2018-05-21 00:58:08
【问题描述】:

我正在尝试使用 Jackson 将对象序列化为 JSON,以便字段名称基于字段类型。

我和this线程中的OP有同样的问题:

但是,它不起作用。

我正在使用 Wildfly 10.1 Final

我做了以下事情:

  • 添加了resteasy-jackson2 依赖项,提供给pom.xml。
  • 创建了我链接的帖子中指定的 CustomSerializer 类。

CustomSerializer 类:

public class CustomSerializer extends JsonSerializer<Object> {
  public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
    jgen.writeStartObject();
    jgen.writeObjectField(value.getClass().getSimpleName(), value);
    jgen.writeEndObject();
  }
}
  • 在对象字段中添加了@JsonProperty("data") 注释,所以我的 Response 类现在看起来像这样:

    public class ResponseWithReturnValue extends Response {
        @JsonProperty("data")
        private Object object;
    
        public ResponseWithReturnValue (int code, String msg) {
            super(code, msg);
        }
    
        public Object getObject() {
            return object;
        }
    
        public void setObject(Object object) {
            this.object = object;
        }
    }
    

当我测试它时,我得到以下 json 对象:

{"code":0,"message":"Success","data":"test"}

因此,@JsonProperty 注释可以正常工作,但自定义 JsonSerializer 不能。

现在,我尝试了 this 博客中的建议,并在我的 ResponseWithReturnValue 类中添加了 @JsonSerialize(using=CustomSerializer.class) 注释。

但是,现在我得到了这个 StackOverflow :) 异常:

Exception in thread "main" java.lang.StackOverflowError
at java.lang.Class.getEnclosingMethodInfo(Class.java:1072)
at java.lang.Class.getEnclosingClass(Class.java:1272)
at java.lang.Class.getSimpleBinaryName(Class.java:1443)
at java.lang.Class.getSimpleName(Class.java:1309)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)
at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:324)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1415)
at rs.netset.authority.web.facade.utils.CustomSerializer.serialize(CustomSerializer.java:13)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2383)

我无法发布完整的堆栈跟踪,因为它太长了。

有什么想法吗?

【问题讨论】:

  • 好吧,serialize、serializeValue、writeValue、writeObject 和 writeObjectField 被无限调用,所以这就是导致 StackOverflowException 的原因,但我不确定是什么原因。
  • 栈溢出往往是无限递归造成的。这就是您的问题的原因。
  • 在查看堆栈跟踪以调试递归问题时,包括前 10 - 15 行,识别重复部分,然后包括底部 10 - 15 行。
  • jgen.writeObjectField(value.getClass().getSimpleName(), value); 看起来不对。第一个参数是字段名,不是类名。

标签: java json jackson wildfly


【解决方案1】:

您通过始终委托给同一个(您的自定义)序列化程序创建了一个无限递归。 jgen.writeObjectField(value.getClass().getSimpleName(), value); 行调用您的自定义序列化程序以序列化Object,它再次调用jgen.writeObjectField(...) 等等。

您可以委托给另一个序列化程序或实际序列化对象:

jgen.writeObjectFieldStart("objectFieldName");
jgen.writeStringField("someValue", value.getSomeValue());
//...
jgen.writeEndObject();

【讨论】:

    猜你喜欢
    • 2017-10-04
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 2012-09-10
    相关资源
    最近更新 更多