适用情况:在使用jackson时,遇到转特殊对象不能成功时,这时需要自定义转换规则.
本文以以json字符串转jsonorg.springframework.validation.FieldError对象为例.
一. 问题:FieldError中字段private修饰字段只有getter方法,所以直接用常规转Bean方式是失败的.以下是FieldError部分源码:
@SuppressWarnings("serial")
public class FieldError extends ObjectError {
private final String field;
@Nullable
private final Object rejectedValue;
private final boolean bindingFailure;
/**
* Create a new FieldError instance.
* @param objectName the name of the affected object
* @param field the affected field of the object
* @param defaultMessage the default message to be used to resolve this message
*/
public FieldError(String objectName, String field, String defaultMessage) {
this(objectName, field, null, false, null, null, defaultMessage);
}
/**
* Create a new FieldError instance.
* @param objectName the name of the affected object
* @param field the affected field of the object
* @param rejectedValue the rejected field value
* @param bindingFailure whether this error represents a binding failure
* (like a type mismatch); else, it is a validation failure
* @param codes the codes to be used to resolve this message
* @param arguments the array of arguments to be used to resolve this message
* @param defaultMessage the default message to be used to resolve this message
*/
public FieldError(String objectName, String field, @Nullable Object rejectedValue, boolean bindingFailure,
@Nullable String[] codes, @Nullable Object[] arguments, @Nullable String defaultMessage) {
super(objectName, codes, arguments, defaultMessage);
Assert.notNull(field, "Field must not be null");
this.field = field;
this.rejectedValue = rejectedValue;
this.bindingFailure = bindingFailure;
}
...
}
二 解决:自定义反序列化器.
1.定义FieldErrorDeserializer,实现JsonDeserializer,覆写deserialize方法,通过FieldError构造方法进行转换.
public class FieldErrorDeserializer extends JsonDeserializer
@Override
public FieldError deserialize(JsonParser jsonParser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
String objectName = JsonUtil.getJsonNodeAsText(node, "objectName");
String defaultMessage = JsonUtil.getJsonNodeAsText(node, "defaultMessage");
String field = JsonUtil.getJsonNodeAsText(node, "field");
String[] codes = JsonUtil.getJsonNodeAsStringArray(node, "codes");
String[] arguments = JsonUtil.getJsonNodeAsStringArray(node, "arguments");
if(!ArrayUtils.isEmpty(arguments) && StringUtils.isEmpty(field) ){
for(JsonNode temp:node.get("arguments")){
field = JsonUtil.getJsonNodeAsText(temp, "code");
}
}
return new FieldError(objectName, field, null, false, codes, arguments, defaultMessage);
}
}
2.将自定义的反序列化器,"注册"到jackson中.定义SelfJackson2Helper实现Jackson2Helper,覆写buildObjectMapper方法.
public class SelfJackson2Helper extends ch.mfrey.jackson.antpathfilter.Jackson2Helper{
public Jackson2Helper(){
super();
}
public ObjectMapper buildObjectMapper(final String... filters) {
ObjectMapper oObjectMapper = super.buildObjectMapper(filters);
oObjectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
oObjectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
oObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
oObjectMapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);
oObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
oObjectMapper.getSerializerProvider().setNullValueSerializer(new ObjectNullSerializer());
//If property don't have @json annotation, will ingore the error.
oObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//Allow json don't use standard format
oObjectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
SimpleModule module = new SimpleModule();
// add FieldErrorDeserializer() to Jackson.
module.addDeserializer(FieldError.class, new FieldErrorDeserializer());
oObjectMapper.registerModule(module);
return oObjectMapper;
}
public SimpleFilterProvider buildFilterProvider(final String... filters) {
SimpleFilterProvider oSimpleFilterProvider = super.buildFilterProvider(filters);
oSimpleFilterProvider.setFailOnUnknownId(false);
//oSimpleFilterProvider.addFilter("customFilter", new AntPathPropertyFilter(filters));
return oSimpleFilterProvider;
}
}
3.使用, 以下是简单验证.
public class JsonUtil {
// json2Bean
public static
T result = null;
SelfJackson2Helper jackson2Helper = ApplicationContextHolder.getContext().getBean(SelfJackson2Helper.class);
ObjectMapper mapper = jackson2Helper.buildObjectMapper();
try {
result = mapper.convertValue(value, toValueTypeRef);
} catch (Exception e) {
LOGGER.error("JsonUtil.convertValue: "+e.getMessage());
}
return result;
}
//main 方法验证...
public static void main(String[] args) {
BindingResult bindingResult = new BeanPropertyBindingResult();
bindingResult.rejectValue("sampleField", "msg_sampleField_not_null");//error
Map
map.put("errors",bindingResult.getAllErrors())
//构造一个FieldError的jsonStr.
String jsonStr = objectMapper.writeValueAsString(map);
//转为FieldError对象.
List>(){});
errorList.stream().forEach(error -> {
System.out.println(error.getField());
});
}
}