一、前言
在接口开发过程中,针对Date类,接口请求参数需要支持不同的格式的日期格式字符串,同样接口的返回值需要根据不同的条件动态的返回不同格式的日期字符串。
自定义序列化:使接口可以同时接收不同格式的日期,比如:yyyy/MM/dd和yyyy-MM-dd
自定义反序列化:使接口可以根据不同的header返回不同格式的日期
二、效果展示
三、源码
DateSerializer
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateSerializer extends JsonSerializer<Date> {
private String pattern = "yyyy/MM/dd";
public DateSerializer() {
}
public DateSerializer(String pattern) {
super();
this.pattern = pattern;
}
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String output = StringUtils.EMPTY;
//根据header参数返回不同格式的日期
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
String dateFormat = request.getHeader("dateFormat");
if (StringUtils.isNotBlank(dateFormat)) {
pattern = dateFormat;
}
if (date != null) {
output = new SimpleDateFormat(pattern).format(date);
}
jsonGenerator.writeString(output);
}
}
DateDeSerializer
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
@Slf4j
public class DateDeSerializer extends JsonDeserializer {
private String pattern = "yyyy/MM/dd";
public DateDeSerializer() {
}
public DateDeSerializer(String pattern) {
super();
this.pattern = pattern;
}
@Override
public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String text = jsonParser.getText();
return DateUtil.parse(text.replaceAll("-", "/"), pattern);
}
}
注解DateFormatter
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DateFormatter {
String pattern() default "yyyy/MM/dd";
}
DateFormatterAnnotationIntrospector
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DateFormatterAnnotationIntrospector extends JacksonAnnotationIntrospector {
private static final long serialVersionUID = 7368707128625539909L;
//自定义序列化
@Override
public Object findSerializer(Annotated annotated) {
String name = annotated.getName();
DateFormatter formatter = annotated.getAnnotation(DateFormatter.class);
if (formatter != null) {
return new DateSerializer(formatter.pattern());//使用注解的日期格式,可以通过注解自定义
}
return super.findSerializer(annotated);
}
//自定义反序列化
@Override
public Object findDeserializer(Annotated annotated) {
String name = annotated.getName();
DateFormatter formatter = annotated.getAnnotation(DateFormatter.class);
if (formatter != null) {
return new DateDeSerializer(formatter.pattern());
}
return super.findDeserializer(annotated);
}
}
WebServerConfig
设置自省程序
objectMapper.setAnnotationIntrospector(new DateFormatterAnnotationIntrospector());
import com.asyf.demo.common.serializer.DateFormatterAnnotationIntrospector;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
@Configuration
public class WebServerConfig {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
// Config the Json convert Chinese garbled.
// 这里的配置可能会导致application.properties文件中spring.jackson.time-zone=GMT+8失效
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 不设置Utf-8格式,可能会导致Mock测试输出信息乱码
converter.setDefaultCharset(StandardCharsets.UTF_8);
ObjectMapper objectMapper = converter.getObjectMapper();
objectMapper.setTimeZone(TimeZone.getDefault());
objectMapper.setAnnotationIntrospector(new DateFormatterAnnotationIntrospector());
objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
return converter;
}
}
DemoDto4
@Data
public class DemoDto4 {
@ApiModelProperty(value = "日期1", example = "2021/12/17")
@DateFormatter
private Date date1;
@ApiModelProperty(value = "日期2", example = "2021-12-17")
@DateFormatter
private Date date2;
}
Controller
@RequestMapping(value = "dateDemo4", method = RequestMethod.POST)
@ApiOperation(value = "日期转换测试-反序列化(自定义注解)")
public Result<?> dateDemo4(@RequestBody DemoDto4 demoDto4) {
log.info(JSONUtil.toJsonStr(demoDto4));
return Result.success(demoDto4);
}