Jackson - 在反序列化期间禁用对象属性和数组元素的null

时间:2014-09-05 19:08:28

标签: java json serialization jackson

当杰克逊遇到null任何(非原始的)对象属性或任何(<)时,是否有选项允许反序列化失败非原始的)数组元素

它应该与Deserialization Feature - FAIL_ON_NULL_FOR_PRIMITIVES)类似。

示例#1

因此反序列化{"name": null}应该在反序列化为POJO时抛出异常

class User { 
    private String name = "Default name";
    //+setters/getters 
}

但是,它应该正常工作,并且在将{}反序列化到该POJO时不会抛出异常,因为name字段的默认值不会被覆盖(请参阅注释)。

示例#2

我也希望避免数组中的null元素,因此反序列化["A", "B", null]会在反序列化为List<String>时抛出异常。

1 个答案:

答案 0 :(得分:1)

据我所知(jackson-databind 2.4.2),没有简单的方法可以做到这一点 我建议你看一下使用custom constructors / factory methods从Json创建对象。这允许您对传入的Json字符串进行更高级的验证。

示例#1的解决方案

您可以通过注册SimpleModule并添加BeanDeserializerModifier来添加此功能,以便更改反序列化功能。
通过覆盖适当的method,您可以使用默认的JsonDeserializer轻松地反序列化对象,并在发生null属性时抛出映射异常。
您可以在类似SO question的答案中找到详细信息。

扩展现有的反序列化:

//instantiate an objectMapper and alter the deserialization functionality
ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.setDeserializerModifier(new BeanDeserializerModifier() {
    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        return new DisallowNullDeserializer(beanDesc.getBeanClass(), deserializer);
    }
});
mapper.registerModule(simpleModule);

实用程序反序列化和异常抛出在此实用程序类中发生:

public class DisallowNullDeserializer<T> extends StdDeserializer<T> implements ResolvableDeserializer {
    private final JsonDeserializer<?> delegateDeserializer;

    public DisallowNullDeserializer(Class<T> clazz, JsonDeserializer<?> delegateDeserializer) {
        super(clazz);
        this.delegateDeserializer = delegateDeserializer;
    }

    @Override
    public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        // delegate actual deserialization to default deserializer
        T out = (T) delegateDeserializer.deserialize(jp, ctxt);

        // check for null properties & throw exception
        // -> there may be a better, more performant way to find null properties
        Map<String, Object> propertyMap = mapper.convertValue(out, Map.class);
        for (Object property: propertyMap.values())
            if (property == null)
                throw ctxt.mappingException("Can not map JSON null values.");

        return out;
    }

    // there is no obvious reason why this is needed; see linked SO answers 
    @Override
    public void resolve(DeserializationContext ctxt) throws JsonMappingException {
        ((ResolvableDeserializer) delegateDeserializer).resolve(ctxt);
    }
}