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

素颜马尾好姑娘i 2023-10-13 13:19 127阅读 0赞

String 转Date类型时,反序列话失败;

  1. caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException:
  2. Can not deserialize value of type java.util.Date from String
  3. 2018-12-25 10:07:49”: not a valid representation (error: Failed to
  4. parse Date value 2018-12-25 10:07:49’: Can not parse date 2018-12-25
  5. 10:07:49Z”: while it seems to fit format
  6. yyyy-MM-ddTHH:mm:ss.SSSZ’’, parsing fails (leniency? null))

首先尝试了 @DateTimeFormat注解,发现没有效果,仍然报错;
然后试了下@JsonFormat注解,接口正常;

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

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

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

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

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

另附原因与多种解决方式

原因

  1. fastjson默认使用的序列化格式:
  2. public static String DEFFAULT_DATE_FORMAT = yyyy-MM-dd
  3. HH:mm:ss”;
  4. jackson默认支持的日期反序列格式:
  5. (“yyyy-MM-ddTHH:mm:ss.SSSZ”, yyyy-MM-ddTHH:mm:ss.SSSZ’”, EEE,dd MMM yyyy HH:mm:ss zzz”, yyyy-MM-dd”))
  6. jackjson解析框架在解析实体类里面是date数据类型的数据时的默认格式是:UTC类型,即yyyy-MM-ddTHH:mm:ss.SSS
  7. 并且默认为+8时区,即时间基础上加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 {
@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);
}
}
}

  1. 1

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

@JsonDeserialize(using = CustomJsonDateDeserializer.class)
private Date txnTime;
使用这种方式,需要重写上面反序列化抽象类

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

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

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

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

  1. 1
  2. 2

需要添加的依赖:

  1. <!-- fastjson -->
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>fastjson</artifactId>
  5. <version>1.2.32</version>
  6. </dependency>
  7. <!-- jackson-->
  8. <dependency>
  9. <groupId>com.fasterxml.jackson.core</groupId>
  10. <artifactId>jackson-databind</artifactId>
  11. <version>2.6.4</version>
  12. </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 list = new ArrayList();
list.add(MediaType.APPLICATION_JSON_UTF8);
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
return mappingJackson2HttpMessageConverter;
}

发表评论

表情:
评论列表 (有 0 条评论,127人围观)

还没有评论,来说两句吧...

相关阅读