Spring boot 在不使用JsonFormat或修改原始类的情况下固定日期的InvalidFormatException 介绍

Spring boot 在不使用JsonFormat或修改原始类的情况下固定日期的InvalidFormatException 介绍,spring-boot,jackson,spring-cloud,json-deserialization,spring-cloud-feign,Spring Boot,Jackson,Spring Cloud,Json Deserialization,Spring Cloud Feign,我们正在使用一个托管在nexus存储库中的定制启动程序,该存储库包含向微服务发出请求的SpringCloud假客户端 其中一个微服务将日期返回为“dd-MM-yyy-HH:MM:ssZ”,这在我们的大多数应用程序中都有效。但是,我们有一个应用程序抛出以下错误: Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date`

我们正在使用一个托管在nexus存储库中的定制启动程序,该存储库包含向微服务发出请求的SpringCloud假客户端

其中一个微服务将日期返回为“dd-MM-yyy-HH:MM:ssZ”,这在我们的大多数应用程序中都有效。但是,我们有一个应用程序抛出以下错误:

Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2019-10-16 14:23:17": not a valid representation (error: Failed to parse Date value '2019-10-16 14:23:17': Unparseable date: "2019-10-16 14:23:1
7")
当前的工作方法 由于我不想污染初学者,我目前的工作是扩展该类,并使用正确的JsonFormat创建本地外部客户机和本地pojo:

public class DocumentMetaDataFix extends DocumentMetaData {
    @JsonFormat(
        shape = Shape.STRING,
        pattern = "yyyy-MM-dd HH:mm:ss"
    )
    private Date creationDate;
    @JsonFormat(
        shape = Shape.STRING,
        pattern = "yyyy-MM-dd HH:mm:ss"
    )
失败的修复 为了尝试从另一个路径影响反序列化,我在配置类中尝试了以下操作。但是,从未调用DocumentMetaDataSerializer。调用ObjectMapperbean

  @Configuration
    @EnableSpringDataWebSupport
    @RequiredArgsConstructor
    public class MyConfig extends WebMvcConfigurerAdapter {

   @Bean
    public Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() {
        return new Jackson2ObjectMapperBuilderCustomizer() {

            @Override
            public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
                jacksonObjectMapperBuilder.deserializerByType(DocumentMetaData.class, new DocumentMetaDataDeserializer());
            }

        };
    }


    @Primary
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
        mapper.setDateFormat(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"));
        //mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, true);
        return mapper;
    }

    @Bean
    public Module dynamoDemoEntityDeserializer() {
        SimpleModule module = new SimpleModule();
        module.addDeserializer(DocumentMetaData.class, new DocumentMetaDataDeserializer());
        return module;
    }

    public static class DocumentMetaDataDeserializer extends JsonDeserializer<DocumentMetaData> {
        @Override
        public DocumentMetaData deserialize(JsonParser jp, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            // return DynamoDemoEntity instance;

            JsonNode node = jp.getCodec().readTree(jp);


            return null;
        }

        public DocumentMetaData deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer t) throws IOException {
            JsonNode node = jp.getCodec().readTree(jp);


            return null;
        }

    }
那么,有什么想法吗? 我已经在整个项目中搜索了杰克逊的参考资料,以防我的项目中有任何其他原因导致这种情况

我将尝试进入ObjectMapper内部,并尝试在ObjectMapper.java:3084上调试stacktace:

at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3084)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:237)
... 67 common frames omitted
更新 我在objectmapper构造函数中添加了一个断点,并且看到它正在从多个位置初始化。这让我怀疑spring boot没有使用我的ObjectMapper。相反,它使用的是一个内部弹簧,它是从
映射Jackson2httpMessageConverter
调用的

<init>:480, ObjectMapper
build:606, Jackson2ObjectMapperBuilder
<init>:59, MappingJackson2HttpMessageConverter
<init>:74, AllEncompassingFormHttpMessageConverter
:480,ObjectMapper
构建:606,Jackson2ObjectMapperBuilder
:59,映射Jackson2HttpMessageConverter
:74,AllEncompassingFormHttpMessageConverter
因此,根据我从以下方面得到的结果,我将尝试超越这个内部弹簧1:

但是这也失败了。

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.serializationInclusion(JsonInclude.Include.NON_NULL);
    builder.propertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
    builder.serializationInclusion(Include.NON_EMPTY);
    builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
    converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));

    //converters.add(cmsaMessageConverter());
    converters.add(new StringHttpMessageConverter());
    converters.add(new FormHttpMessageConverter());
    converters.add(new MappingJackson2HttpMessageConverter());
}


@Bean
public Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() {
    return new Jackson2ObjectMapperBuilderCustomizer() {

        @Override
        public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
            jacksonObjectMapperBuilder.deserializerByType(DocumentMetaData.class, new DocumentMetaDataDeserializer());
        }

    };
}


@Primary
@Bean
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
    mapper.setDateFormat(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"));
    //mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, true);
    return mapper;
}

@Bean
public Module dynamoDemoEntityDeserializer() {
    SimpleModule module = new SimpleModule();
    module.addDeserializer(DocumentMetaData.class, new DocumentMetaDataDeserializer());
    return module;
}

public static class DocumentMetaDataDeserializer extends JsonDeserializer<DocumentMetaData> {
    @Override
    public DocumentMetaData deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        // return DynamoDemoEntity instance;

        JsonNode node = jp.getCodec().readTree(jp);


        return null;
    }

    public DocumentMetaData deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer t) throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);


        return null;
    }

}
参考资料

  • 非常有用:
  • 更新-尝试的最终列表 它仍然会失败并出现错误。

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        builder.propertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
        builder.serializationInclusion(Include.NON_EMPTY);
        builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
    
        //converters.add(cmsaMessageConverter());
        converters.add(new StringHttpMessageConverter());
        converters.add(new FormHttpMessageConverter());
        converters.add(new MappingJackson2HttpMessageConverter());
    }
    
    
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() {
        return new Jackson2ObjectMapperBuilderCustomizer() {
    
            @Override
            public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
                jacksonObjectMapperBuilder.deserializerByType(DocumentMetaData.class, new DocumentMetaDataDeserializer());
            }
    
        };
    }
    
    
    @Primary
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
        mapper.setDateFormat(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"));
        //mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, true);
        return mapper;
    }
    
    @Bean
    public Module dynamoDemoEntityDeserializer() {
        SimpleModule module = new SimpleModule();
        module.addDeserializer(DocumentMetaData.class, new DocumentMetaDataDeserializer());
        return module;
    }
    
    public static class DocumentMetaDataDeserializer extends JsonDeserializer<DocumentMetaData> {
        @Override
        public DocumentMetaData deserialize(JsonParser jp, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            // return DynamoDemoEntity instance;
    
            JsonNode node = jp.getCodec().readTree(jp);
    
    
            return null;
        }
    
        public DocumentMetaData deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer t) throws IOException {
            JsonNode node = jp.getCodec().readTree(jp);
    
    
            return null;
        }
    
    }
    
    @覆盖
    public void configureMessageConverters(列表尝试使用LocalDateTime,
    这就是我正在做的,为我工作

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime date;