一,背景介绍
鉴于之前fastjson的黑历史,慢慢的就把json处理交给了Jackson。当然要对Jackson动手,需要先了解一下常规用法:
序列化和反序列化:
public class JSON {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
/**
* 将对象输出为json字符串
*
* @param object 对象
* @param prettyFormat 美化格式
* @return
*/
public static String toJSONString(Object object, boolean prettyFormat) {
try {
if (prettyFormat) {
return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
}
return OBJECT_MAPPER.writeValueAsString(object);
} catch (Throwable e) {
throw new JSONException(e);
}
}
/**
* 反序列化解析为指定类
*
* @param text
* @param clazz
* @param <T>
* @return
*/
public static <T> T parse(String text, Class<T> clazz) {
if (text == null || text.isEmpty()) {
return null;
}
try {
return OBJECT_MAPPER.readValue(text, clazz);
} catch (Throwable e) {
throw new JSONException(e);
}
}
}
如果遇到例如Date格式,则需要在对应的属性名上增加注解,例如:@JsonFormat来指定格式交由Jacson反序列化,或者@JsonDeserialize来指定自定义反序列化。
我们以@JsonDeserialize为例:
要将带有Date的json串自定义反序列化,一般情况下是继承JsonDeserializer,然后重写deserialize方法:
public class SimpleDateDeserializer extends JsonDeserializer<Date> {
private static final String[] PARSE_PATTERNS = new String[]{
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd"};
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
//这里增加了对时间戳的反序列化
int tokenId = jp.getCurrentTokenId();
if (tokenId == JsonTokenId.ID_NUMBER_INT) {
return new Date(jp.getValueAsLong());
}
try {
String value = jp.getValueAsString();
return value == null ? null : DateUtils.parseDate(value, PARSE_PATTERNS);
} catch (ParseException e) {
throw new IOException(e);
}
}
}
缺点也显而易见,只支持三种格式,时间戳,时间日期,日期,其实除了时间戳,反序列化的瓶颈在于任何时间的属性,都要在字段上增加以上的两个注解,如果不加注解呢?如果是Date的toString()方法呢?答案是解析失败。
二,解决方法
先看结果:
方法一:
//一般的ObjectMapper类
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule