在 Spring 引导中使用 Jackson 反序列化 Date 对象

Deserialize Date object with Jackson in Spring boot

我的数据对象 returns 数据为 1604571544010,我需要更具可读性的内容。

我尝试了很多东西,但似乎没有任何效果,我怀疑 Jackson 或 spring 版本有问题。

我尝试在application.properties

中设置数据格式

我还尝试了 baeldung

中的所有全局配置

Pom.xml

<jackson.version>2.11.3</jackson.version>
<jackson.databind.version>2.11.3</jackson.databind.version>
<jackson.mapper.version>1.9.13</jackson.mapper.version>
<spring.boot.version>2.1.17.RELEASE</spring.boot.version>
<spring.version>5.1.18.RELEASE</spring.version>

WebConfig

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder()
{
    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    return new Jackson2ObjectMapperBuilder().indentOutput(true).dateFormat(sdf);
}

DTO

@JsonProperty
public Date getStartDateTime()
{
    return startDateTime;
}

使用@JsonComponent。任何 Date 类型都将使用此自定义序列化程序进行序列化。

@JsonComponent
class DateSerializer extends JsonSerializer<Date> {

    public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());

    public DateSerializer() {
        this(null);
    }

    public DateSerializer(Class<Date> t) {
        super(t);
    }

    @Override
    public void serialize(
        Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {


        jgen.writeString(sdf.format(value));

    }
}

不使用@JsonComponent

WebConfiguration 中注册自定义序列化程序。

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        SimpleModule m = new SimpleModule();
        m.addSerializer(Date.class, new DateSerializer());
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().modules(m);
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
    }
}

或者如果要标记每个字段

@JsonSerialize(using = DateSerializer.class)
public Date getStartDateTime()
    {
        return startDateTime;
    }

您可以在 application.properties 中添加 属性 spring.jackson.date-format 以提供 java.util.Date 的特定日期格式。

例如。 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

来源:Spring-Boot application.properties

唯一对我有用的全局设置是 ObjectMapper

   @Bean
        @Primary
        public ObjectMapper objectMapper()
        {
            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
            final ObjectMapper mapper = new ObjectMapper();
            mapper.setDateFormat(sdf);
            mapper.enable(SerializationFeature.INDENT_OUTPUT);
            return mapper;
        }

全局解决方案:

    @Slf4j
    @JsonComponent
    public class CustomDateDeserializer extends StdDeserializer<Date> {
        
        private static final long serialVersionUID = 1L;
        private final DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
                .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"))
                .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"))
                .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"))
                .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ"))
                .toFormatter();

        public CustomDateDeserializer() {
            this(null);
        }

        public CustomDateDeserializer(Class<?> vc) {
            super(vc);
        }

        @Override
        public Date deserialize(JsonParser jsonparser, DeserializationContext context)
                throws IOException, JsonProcessingException {
            String date = jsonparser.getText();
            //if(date == null || date.isBlank()) return null;
            if (NumberUtils.isParsable(date)) {
                try {
                    return new Date(Long.parseLong(date));
                } catch (Exception e) {
                    log.trace("Long Unparseable date: \"" + date + "\"");
                    throw new RuntimeException("LongUnparseable date: \"" + date + "\"");
                }
            }
            try {
            LocalDateTime dateToConvert = LocalDateTime.parse(jsonparser.getText(), dateFormatter);
            return java.sql.Timestamp.valueOf(dateToConvert);
            } catch (Exception e) {
                log.error("Error parsing date: \"" + date + "\" : ", e);
                throw new RuntimeException("Unparseable date: \"" + date + "\"");
            }
            
        }

    }

`

这与 Chayne 发布的解决方案相同,但使用 DateTimeFormatter 而不是 SimpleDateFormat,因为 DateTimeFormatter 是线程安全的。