jackson deserialization failed InvalidFormatException: Can not deserialize value of type java.util.Date

When converting String to Date type, the deserialization session fails;

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))

First tried the @DateTimeFormat annotation, found no effect, and still reported an error;
then tried the @JsonFormat annotation, and the interface was normal;

In my impression, @DateTimeFormat is for data format conversion when entering parameters, and @JsonFormat is for format conversion when outputting parameters, why it suddenly fails.

After some searching, I found the following explanation:

Generally, @DateTimeFormat is used to convert the time string passed to the background into Date, and @JsonFormat is used to convert the Date transmitted from the background into a time string, but @DateTimeFormat will only be used in request parameters similar to @RequestParam (url splicing parameters It will only take effect, if it is placed in the form-data in RequestBody, it will be invalid), and if @DateTimeFormat is placed under @RequestBody, it will be invalid.

In @RequestBody, you can use @JsonFormat to convert the time string passed to the background into Date, which means that @JsonFormat can actually convert the time string passed to the background into Date or convert the Date passed from the background into time string.

As for why it didn't work, I didn't elaborate. From the analysis of the error report, it should be that the way of desequencing the words is different, resulting in the @DateTimeFormat annotation not taking effect.

Additional reasons and multiple solutions

reason

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框架

Solution 1: Rewrite jackson deserialization

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 override deserialization
  • @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

Add annotations on the required date attributes:

@JsonDeserialize(using = CustomJsonDateDeserializer.class)
private Date txnTime;
In this way, you need to rewrite the deserialization abstract class above

Solution 2: Use the @JsonFormat annotation to specify the required receiving format without rewriting deserialization:

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

1
2
3

Solution 3: If the jackjson framework is excluded, use fastjson annotations and do not rewrite deserialization

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

1
2

Dependencies that need to be added:

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

Finally, a way to globally modify the receiving time format is introduced

Use MappingJackson2HttpMessageConverter to configure the Application.Java startup class and specify the receiving format. I do not recommend it, because it is global and not very flexible, so just understand it

@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;
}

Guess you like

Origin blog.csdn.net/qq_34690003/article/details/131596800