# 日期格式解析问题解决方案

README.md

复制代码
## 问题描述

前端发送请求到 `/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` 类型的字段都有效

1.添加MultiFormatDateDeserializer类,支持多种日期格式的解析:

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