开发者

解决jackson反序列化失败InvalidFormatException:Can not deserialize value of type java.util.Date

目录
  • 反序列化失败
  • 通过一番搜索,找到了如下解释
  • 另附原因与多种解决方式
    • 原因
    • 解决办法一
    • 解决办法二
    • 解决办法三
    • 最后介绍一种全局修改接收时间格式的方式
  • 总结

    今天调试接口的时候碰到了这个问题,String 转Date类型时

    反序列化失败

    caused by: com.fasterXML.jackson.databind.exc.InvalidFormatException:

    Can not deserialize value of type Java.util.Date from String

    “2018-12-25 10:07:49”: not a valid representation (error: Failed to

    parse Date value ‘2018-12-25 10:07:49’: Can not parse date “2018-12-25

    10:07:49Z”: while it seems to fit format

    ‘yyyy-MM-dd’T’HH:mm:ss.SSS’Z’’, parsing fails (leniency? null))

    首先尝试了 @DateTimeFormat注解,发现没有效果,仍然报错;

    然后试了下@jsonFormat注解,接口正常;

    在印象中,@DateTimeFormat是入参时进行数据格式化转换,@JsonFormat是出参进行格式话转换,为啥突然不行了呢。

    通过一番搜索,找到了如下解释

    android般都是使用@DateTimeFormat把传给后台的时间字符串转成Date,使用@JsonFormat把后台传出的Date转成时间字符串,但是@DateTimeFormat只会在类似@RequestParam的请求参数(url拼接的参数才生效,如果是放到RequestBody中的form-data也是无效的)上生效,如果@DateTimeFormat放到@RequestBody下是无效的。

    在@RequestBody中则可以使用@JsonFormat把传给后台的时间字符串转成Date,也就是说@JsonFormat其实既可以把传给后台的时间字符串转成Date也可以把后台传出的Date转成时间字符串。

    至于为啥没效果,没有细说,从报错的分析来看应该是反序列话的方式不同,导致@DateTimeFormat注解不能生效。

    另附原因与多种解决方式

    原因

    fastjson默认使用的序列化格式:

    public static String DEFFAULT_DATE_FORMAT = “yyyy-MM-dd
    HH:mm:ss”;

    jackson默认支持的日期反序列格式:

    (“yyyy-MM-dd'T'HH:mm:ss.SSSZ”, “yyyy-MM-dd'T'HH:mm:ss.SSS'Z'”, “EEE,dd MMM yyyy HH:mm:ss zzz”, “yyyy-MM-dd”))

    jackjson解析框架在解析实体类里面是date数据类型的数据时的默认格式是:UTC类型,即yyyy-MM-dd’T’HH:mm:ss.SSS

    并且默认为+8时区,即时间基础上加8小时,

    Springboot使用的默认json解析框架是jackjson框架

    解决办法一

    重写jackson反序列化

    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 java.io.IOException;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * @version 1.0.0
     * @description 重写反序列化
     * @date 2018/12/25 9:51
     **/
    
    public class CustomJsonDateDeserializer extends JsonDeserializer<Date> {
    @Override
        public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date = jp.getText();
            try {
                return format.parse(date);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
          }
        }

    在需要的datejavascript属性上添加注解:

    @JsonDeserialize(using = CustomJsonDateDeserializer.class)
    private Date txnTime;

    使用这种方式,需要重写上面反序列化抽象类

    解决办法二

    使用@JsonFormat注解指定所需的接收格式,不需要重写反序列化:

        //GMT+8表示时区,东八区,需加上时区,shape www.devze.com默认是JsonFormat.Shape.ANY,
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private Date txnTime;uVFcogeogQ

    解决办法三

    如果排除了jackjson框架则使用fastjson注解,不要重写反序列化

    @JSONField(format = “yyyy-MM-dd HH:mm:ss”)
    private Date txnTime;

    需要添加的依赖:

        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.32</version>
        </dependency>
        <!-- jackson-->
        &phplt;dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.4</version>
        </dependency>

    最后介绍一种全局修改接收时间格式的方式

    用MappingJackson2HttpMessageConverter配置在Application.Java启动类,指定接收格式,本人不推荐使用,因为这是全局性的,不是很灵活,因此了解即可

    @Bean
        public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() {
            MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
            //设置日期格式
            ObjectMapper objectMapper = new ObjectMapper();
            SimpleDateFormat smt = new SimpleDateFormat("yyyy-MM-dd");
            objectMapper.setDateFormat(smt);
            mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
            //设置中文编码格式
            List<MediaType> list = new ArrayList<MediaType>();
            list.add(MediaType.APPLICATION_JSON_UTF8);
            mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
            return mappingJackson2HttpMessageConverter;
        }

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜