背景
@JsonFormat用在接口的返回对象属性上时,能够对Date进行格式化处理
@Data
public class UserVo {
//注意带时分秒的要指定时区
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date date1;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date date2;
}
{
"date1": "2018-11-30 16:21:57",
"date2": "2018-11-30"
}
但笔者项目中这样注解不生效,经过代码分析原来是有继承JsonSerializer接口,自定义了Date的转换,那么JsonFormat就失效了,因为自定义的会覆盖JsonFormat的格式化,这是一种通用的处理方式
public class JavaDateJsonSerializer extends JsonSerializer<Date>{
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
public JavaDateJsonSerializer() {
}
public void serialize(Date arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException, JsonProcessingException {
if (null != arg0) {
arg1.writeString(this.df.format(arg0));
}
}
}
这样的话,所有的Date在json序列化时都会格式化为yyyy-MM-dd,是一种简单的全局处理方式,但如果一个返回对象的两个Date想返回不同的格式如何处理呢。
ContextualSerializer
将自定义的JavaDateJsonSerializer实现一下ContextualSerializer接口的createContextual方法,然后稍作文章即可
public class JavaDateJsonSerializer extends JsonSerializer<Date> implements ContextualSerializer {
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
public JavaDateJsonSerializer() {
}
public void serialize(Date arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException, JsonProcessingException {
if (null != arg0) {
arg1.writeString(this.df.format(arg0));
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
AnnotationMap annotated = property.getMember().getAllAnnotations();
JsonFormat jsonFormat = annotated.get(JsonFormat.class);
if (jsonFormat != null && jsonFormat.pattern() != null){
df = new SimpleDateFormat(jsonFormat.pattern());
}
return this;
}
}
createContextual的调用是先于serialize的,createContextual传入了BeanProperty,通过它能获取了到属性的注解,即JsonFormat进而也能获取到JsonFormat中的pattern,接着就可以创建SimpleDateFormat了。这样不实用JsonFormat注解就用默认的格式化,使用JsonFormat注解就根据pattern格式化。