复制代码
## 问题描述
前端发送请求到 `/saveDiagnoseRegister` 接口时,出现日期格式解析错误:
```
Cannot deserialize value of type `java.util.Date` from String "2025/08/20 10:50:01": not a valid representation
```
## 问题原因
前端发送的日期格式 `"2025/08/20 10:50:01"` 与后端 `MzzyJyjcjghrbjb` 实体类中 `HRRQ` 字段的 `@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")` 注解不匹配。
## 解决方案
### 1. 创建自定义日期反序列化器
创建了 `MultiFormatDateDeserializer` 类,支持多种日期格式的解析:
- `yyyy/MM/dd HH:mm:ss`
- `yyyy-MM-dd HH:mm:ss`
- `yyyy/MM/dd`
- `yyyy-MM-dd`
- `yyyy/MM/dd HH:mm`
- `yyyy-MM-dd HH:mm`
### 2. 配置全局Jackson
创建了 `JacksonConfig` 配置类,注册自定义的日期反序列化器,使其能够自动处理多种日期格式。
### 3. 保持实体类注解不变
保持 `MzzyJyjcjghrbjb` 实体类中的 `@JsonFormat` 注解不变,确保输出格式的一致性。
## 使用方法
1. 重启应用后,Jackson配置会自动生效
2. 前端可以发送以下任意格式的日期:
- `"2025/08/20 10:50:01"`
- `"2025-08-20 10:50:01"`
- `"2025/08/20"`
- `"2025-08-20"`
## 测试
运行 `JacksonConfigTest` 测试类可以验证配置是否正确工作。
## 注意事项
1. 如果前端发送的日期格式不在支持列表中,会抛出详细的错误信息
2. 输出格式仍然按照实体类中的 `@JsonFormat` 注解进行格式化
3. 此配置对所有使用 `java.util.Date` 类型的字段都有效
java
复制代码
/**
* 支持多种日期格式的反序列化器
*/
public class MultiFormatDateDeserializer extends JsonDeserializer<Date> {
private static final String[] DATE_FORMATS = {
"yyyy/MM/dd HH:mm:ss",
"yyyy-MM-dd HH:mm:ss",
"yyyy/MM/dd",
"yyyy-MM-dd",
"yyyy/MM/dd HH:mm",
"yyyy-MM-dd HH:mm"
};
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String dateStr = p.getText();
if (!StringUtils.hasText(dateStr)) {
return null;
}
// 尝试多种日期格式
for (String format : DATE_FORMATS) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setLenient(false); // 严格模式
return sdf.parse(dateStr);
} catch (ParseException e) {
// 继续尝试下一个格式
continue;
}
}
// 如果所有格式都失败,抛出异常
throw new IOException("无法解析日期字符串: " + dateStr +
",支持的格式: " + String.join(", ", DATE_FORMATS));
}
}
2.添加Jackson配置类,支持多种日期格式的解析
java
复制代码
/**
* Jackson配置类
* 支持多种日期格式的解析
*/
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 配置日期格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
// 配置Java 8时间类型
SimpleModule javaTimeModule = new SimpleModule();
// 支持多种日期格式的序列化
DateTimeFormatter[] formatters = {
DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"),
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
DateTimeFormatter.ofPattern("yyyy/MM/dd"),
DateTimeFormatter.ofPattern("yyyy-MM-dd")
};
// LocalDateTime序列化和反序列化
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatters[0]));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatters[0]));
// LocalDate序列化和反序列化
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(formatters[2]));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(formatters[2]));
// 注册自定义的Date反序列化器,支持多种格式
javaTimeModule.addDeserializer(Date.class, new MultiFormatDateDeserializer());
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
}
3.Jackson配置测试类
java
复制代码
/**
* Jackson配置测试类
*/
@SpringBootTest
public class JacksonConfigTest {
@Test
public void testMultiFormatDateDeserialization() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
// 注册自定义的Date反序列化器
objectMapper.registerModule(new com.fasterxml.jackson.databind.module.SimpleModule()
.addDeserializer(Date.class, new MultiFormatDateDeserializer()));
// 测试不同的日期格式
String[] dateFormats = {
"{\"HRRQ\": \"2025/08/20 10:50:01\"}",
"{\"HRRQ\": \"2025-08-20 10:50:01\"}",
"{\"HRRQ\": \"2025/08/20\"}",
"{\"HRRQ\": \"2025-08-20\"}"
};
for (String json : dateFormats) {
try {
MzzyJyjcjghrbjb entity = objectMapper.readValue(json, MzzyJyjcjghrbjb.class);
assertNotNull(entity.getHrrq(), "日期应该被正确解析: " + json);
System.out.println("成功解析日期格式: " + json + " -> " + entity.getHrrq());
} catch (Exception e) {
fail("应该能够解析日期格式: " + json + ", 错误: " + e.getMessage());
}
}
}
@Test
public void testInvalidDateFormat() {
ObjectMapper objectMapper = new ObjectMapper();
// 注册自定义的Date反序列化器
objectMapper.registerModule(new com.fasterxml.jackson.databind.module.SimpleModule()
.addDeserializer(Date.class, new MultiFormatDateDeserializer()));
String invalidJson = "{\"HRRQ\": \"invalid-date-format\"}";
assertThrows(Exception.class, () -> {
objectMapper.readValue(invalidJson, MzzyJyjcjghrbjb.class);
}, "无效的日期格式应该抛出异常");
}
}
java
复制代码
/**
* MultiFormatDateDeserializer测试类
*/
public class MultiFormatDateDeserializerTest {
@Test
public void testValidDateFormats() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Date.class, new MultiFormatDateDeserializer());
objectMapper.registerModule(module);
// 测试有效的日期格式
String[] validFormats = {
"2025/08/20 10:50:01",
"2025-08-20 10:50:01",
"2025/08/20",
"2025-08-20",
"2025/08/20 10:50",
"2025-08-20 10:50"
};
for (String dateStr : validFormats) {
try {
Date date = objectMapper.readValue("\"" + dateStr + "\"", Date.class);
assertNotNull("日期应该被正确解析: " + dateStr, date);
System.out.println("成功解析: " + dateStr + " -> " + date);
} catch (Exception e) {
fail("应该能够解析日期: " + dateStr + ", 错误: " + e.getMessage());
}
}
}
@Test
public void testInvalidDateFormat() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Date.class, new MultiFormatDateDeserializer());
objectMapper.registerModule(module);
// 测试无效的日期格式
String invalidDate = "invalid-date-format";
try {
objectMapper.readValue("\"" + invalidDate + "\"", Date.class);
fail("应该抛出异常");
} catch (Exception e) {
assertTrue("应该包含错误信息", e.getMessage().contains("无法解析日期字符串"));
System.out.println("正确捕获无效日期格式: " + e.getMessage());
}
}
@Test
public void testNullAndEmptyValues() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Date.class, new MultiFormatDateDeserializer());
objectMapper.registerModule(module);
// 测试null值
Date nullDate = objectMapper.readValue("null", Date.class);
assertNull("null值应该返回null", nullDate);
// 测试空字符串
Date emptyDate = objectMapper.readValue("\"\"", Date.class);
assertNull("空字符串应该返回null", emptyDate);
}
}