【问题标题】:REST Jackson JsonDeserialize, StackOverflowError after upgradeREST Jackson JsonDeserialize, StackOverflowError 升级后
【发布时间】:2015-03-22 11:16:41
【问题描述】:

在以前版本的 jackson (1.9.2) 中,以下代码运行良好:

import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.DeserializationContext;
...
@JsonDeserialize(using = RoleDeserializer.class)
public interface RoleDto {}

public class RoleDeserializer extends SomeSharedDeserializer<RoleDto> {}

public class SomeSharedDeserializer<T> extends JsonDeserializer<T> {
    @Override
    public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
    {
        return jp.readValueAs(getImplementation());
    }

    public Class<? extends T> getImplementation(){ ... returns some generated implementation of RoleDto }
}

在我们迁移到最后一个 jackson 版本(Wildfly 8.2 提供的 1.9.13)后,我们遇到了一个异常:

com.fasterxml.jackson.databind.JsonMappingException: 无法构造 RoleDto 的实例,问题:要么需要映射抽象类型 具体类型,具有自定义反序列化器,或被实例化 附加类型信息

好的,因为在jackson中使用了新包,我们将它们升级为:

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer;

反序列化器现在可见(之前的异常消失了), 但是,我们得到 StackOverflowError 异常。 com.fasterxml.jackson.databind.ObjectMapper 读取值(第 3023 行):

    DeserializationContext ctxt = createDeserializationContext(jp, cfg);
    JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
    // ok, let's get the value
    if (cfg.useRootWrapping()) {
        result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser);
    } else {
        result = deser.deserialize(jp, ctxt);
    }

我们去排队:result = deser.deserialize(jp, ctxt);

它会导致无限循环和 StackOverflowError 结果。

推荐的方法之一是将我们自己的 SomeSharedDeserializer 实现为:

ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
//here manually create new object and return it

但是我们的类是生成的。作为另一种解决方案,我尝试使用

ObjectMapper mapper = new ObjectMapper();
mapper.readValue(jp, getImplementation());

但得到了相同的结果 - StackOverflow 异常。

我们该如何解决?我们可以使用一些反序列化器,将 JsonParser 实例传递给它,生成实现基接口且没有 StackOverflowError 的类吗?

【问题讨论】:

    标签: java json rest jackson deserialization


    【解决方案1】:

    Here 是您可以找到完整的描述和试验以找到解决方案。 已找到以下解决方案:

    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.databind.BeanDescription;
    import com.fasterxml.jackson.databind.DeserializationConfig;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
    import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
    import com.fasterxml.jackson.databind.deser.BeanDeserializerFactory;
    import com.fasterxml.jackson.databind.deser.ResolvableDeserializer;
    import com.fasterxml.jackson.databind.type.SimpleType;
    ...
        public abstract class RestDtoDeserializer<T> extends JsonDeserializer<T>
        {
            @Override
            public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
            {
                DeserializationConfig config = ctxt.getConfig();
                SimpleType simpleType = SimpleType.construct(getImplementationClass());
                BeanDescription beanDesc = config.introspect(simpleType);
                BeanDeserializerFactory instance = new BeanDeserializerFactory(new DeserializerFactoryConfig());
                JsonDeserializer deserializer = instance.buildBeanDeserializer(ctxt, simpleType, beanDesc);
                ((ResolvableDeserializer)deserializer).resolve(ctxt);
                return (T) deserializer.deserialize(jp, ctxt);
            }
    
            public abstract Class<? extends T> getImplementationClass();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-29
      • 2015-10-15
      • 1970-01-01
      • 1970-01-01
      • 2018-05-30
      • 1970-01-01
      • 2018-02-22
      相关资源
      最近更新 更多