杰克逊AtomicLong的多态序列化问题

时间:2018-01-09 16:26:39

标签: jackson

我需要在其树中包含AtomicLong的{​​{3}} Java类。

我初始化 Jackson 2.9.2 的ObjectMapper如下

private final static ObjectMapper objectMapper = new ObjectMapper()///
    .findAndRegisterModules()//
    .enableDefaultTyping(DefaultTyping.NON_FINAL, As.WRAPPER_OBJECT)//
    .setDefaultPrettyPrinter(new MinimalPrettyPrinter())//
    .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)//
    .disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)//
    .disable(SerializationFeature.INDENT_OUTPUT)//
    .enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);

然后我将我的类序列化为JSON,为此我显示了罪魁祸首片段

"progress":{"com.acme.SimpleProgressObject":{"current":0,"total":null,"status":null,"error":null,"innerProgress":null}}

注意current等于plain 0. Class由

组成
public class SimpleProgressObject implements AsyncProgress, AsyncProgressSupplier, Serializable
{
    private final AtomicLong current = new AtomicLong(0);
    private AtomicLong total;
    private String status;
    private Throwable error;
    private SimpleProgressObject innerProgress;
}

当我从容器中反序列化这些东西时,我收到以下错误

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_NUMBER_INT), expected START_OBJECT: need JSON Object to contain As.WRAPPER_OBJECT type information for class java.util.concurrent.atomic.AtomicLong
 at [Source: [truncated]; line: 1, column: 145] (through reference chain: ProcessExecutionContext["progress"]->SimpleProgressObject["current"])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
    at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1498)
    at com.fasterxml.jackson.databind.DeserializationContext.reportWrongTokenException(DeserializationContext.java:1273)
    at com.fasterxml.jackson.databind.jsontype.impl.AsWrapperTypeDeserializer._deserialize(AsWrapperTypeDeserializer.java:100)
    at com.fasterxml.jackson.databind.jsontype.impl.AsWrapperTypeDeserializer.deserializeTypedFromObject(AsWrapperTypeDeserializer.java:52)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1156)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.jsontype.impl.AsWrapperTypeDeserializer._deserialize(AsWrapperTypeDeserializer.java:121)
    at com.fasterxml.jackson.databind.jsontype.impl.AsWrapperTypeDeserializer.deserializeTypedFromObject(AsWrapperTypeDeserializer.java:52)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1156)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.jsontype.impl.AsWrapperTypeDeserializer._deserialize(AsWrapperTypeDeserializer.java:121)
    at com.fasterxml.jackson.databind.jsontype.impl.AsWrapperTypeDeserializer.deserializeTypedFromObject(AsWrapperTypeDeserializer.java:52)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1156)
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)

我认为正确的JSON可能已经(美化)

{
   "progress":{
      "com.acmeSimpleProgressObject":{
         "current":{
            "java.util.concurrent.AtomicLong":0
         },
         "total":null,
         "status":null,
         "error":null,
         "innerProgress":null
      }
   }
}

问题是:我的代码是错误的还是杰克逊本身的问题?我没有怀疑在Github上打开一个问题

编辑1:改变.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY)//

也是如此

1 个答案:

答案 0 :(得分:0)

不幸的是我没有发布getter / setter,这有助于理解罪魁祸首

@Override
public Long getCurrent()
{
    if (current == null)
        return null;
    return current.longValue();
}

@Override
public Long getTotal()
{
    if (total == null)
        return null;
    return total.longValue();
}

@Override
public void setTotal(Long total)
{
    if (total == null)
        this.total = null;
    else
        this.total = new AtomicLong(total);
}

@Override
public String getStatus()
{
    return status;
}

@Override
public void setStatus(String status)
{
    this.status = status;
}

@Override
public Throwable getError()
{
    return error;
}

由于我有current的getter返回Long,因此Jackson使用它将其序列化为基本类型,而不包装。它实际上不是一个getter,而是一种遵守接口契约的实用方法。

然而,当反序​​列化时,杰克逊能够通过反射设置最终字段,但在有效负载中找到原始值。后者是正确的行为,但是由我的非规范吸气剂引起。

我的解决方案是添加一个接受@JsonSetter("current") Long current

的参数化私有构造函数

我希望立即关闭这个问题,因为它与我的案例非常具体,但在找到原因的所有努力之后,我要求社群决定这个问题的生命。