当遇到任何(非基元)对象属性或任何(非基元)数组元素的null
时,Jackson中是否有让反序列化失败的选项?
它的工作原理应类似于反序列化功能(FAIL_ON_NULL_FOR_PRIMITIVES)。
示例#1
因此,当反序列化为POJO 时,反序列化{"name": null}
应该抛出异常
class User {
private String name = "Default name";
//+setters/getters
}
但是,当将{}
反序列化到该POJO中时,它应该可以正常工作,并且不会引发异常,因为name
字段的默认值不会被覆盖(请参阅注释)。
示例#2
我也希望避免数组中的null
元素,因此反序列化["A", "B", null]
在反序列化为List<String>
时应该引发异常。
据我所知,没有简单的方法可以做到这一点(jackson databind 2.4.2)。
我建议您考虑使用自定义构造函数/工厂方法从Json中创建对象。这允许您对传入的Json字符串进行更高级的验证。
示例#1的解决方案
您可以通过向添加的BeanDeserializerModifier
注册SimpleModule
来添加此功能,以便更改反序列化功能
通过重写适当的方法,您可以使用默认的JsonDeserializer
来轻松地反序列化对象,并在发生null
属性时抛出映射异常
您可以在类似SO问题的答案中找到详细信息。
扩展现有的反序列化:
//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);
}
}