issue1:使用Jackson反序列化 诸如 yyyy/MM/dd 和 yyyy-MM-dd 或者 MM/dd/yyyy 格式的日期数据。
1)通过使用 @JsonFormat
注解s,可以轻松地反序列化特定格式的日期字符串
2)不添加注解, 通过改变objectMapper的方式,来支持特定格式日期的反序列化
可以通过配置 ObjectMapper
的方式来处理 yyyy/MM/dd
格式的日期,而无需在类中添加注解。可以使用 SimpleDateFormat
来设置全局日期格式。
示例代码
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class DateExample { static class MyData { private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } } public static void main(String[] args) { String json = "{\"date\": \"2024/10/15\"}"; ObjectMapper objectMapper = new ObjectMapper(); // 设置日期格式 objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd")); // 可选:启用 Java 8 日期时间模块(如果使用 LocalDate 等) objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try { MyData myData = objectMapper.readValue(json, MyData.class); System.out.println("Deserialized Date: " + myData.getDate()); } catch (IOException e) { e.printStackTrace(); } } }
解释
- 设置日期格式:
- 使用
objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd"));
设置全局日期格式。
- 使用
- 反序列化:
- 将 JSON 字符串反序列化为
MyData
对象时,ObjectMapper
会自动使用指定的日期格式。
- 将 JSON 字符串反序列化为
输出结果
运行上述代码,反序列化后的 Date
对象:
Deserialized Date: Tue Oct 15 00:00:00 UTC 2024
结论
通过修改 ObjectMapper
的配置,可以灵活地处理日期格式,而无需在每个数据类中添加注解。这种方法在需要统一处理多个类的日期格式时尤其有用。
3)通过改变objectMapper的方式,来支持多种格式日期的反序列化
要实现一个 ObjectMapper
,既支持 yyyy/MM/dd
格式又支持 yyyy-MM-dd
格式的日期反序列化,可以使用自定义的 DateDeserializer
。 下面是示例代码,当然,据此我们依然可以按需扩展其他有效的时间格式,如MM/dd/yyyy。
解释
自定义反序列化器:
CustomDateDeserializer
类实现了JsonDeserializer<Date>
,并定义了两个日期格式:yyyy/MM/dd
和yyyy-MM-dd
。- 在
deserialize
方法中,首先尝试使用第一种格式解析,如果失败,则尝试第二种格式。
注册自定义反序列化器:
- 创建
SimpleModule
并添加自定义反序列化器,然后将其注册到ObjectMapper
。
- 创建
反序列化示例:
- 提供两个 JSON 字符串,分别使用不同的日期格式进行反序列化。
输出结果
Deserialized Date (yyyy/MM/dd): Tue Oct 15 00:00:00 UTC 2024
Deserialized Date (yyyy-MM-dd): Tue Oct 15 00:00:00 UTC 2024
结论
通过自定义反序列化器,我们可以灵活地处理多种日期格式,从而满足不同的输入需求。
issue2:SpringMVC如何支持多种有效日期的反序列化
SpringMVC使用Jackson序列化。
在 Spring Boot MVC 中支持多种日期格式的反序列化,可以通过自定义消息转换器或使用自定义的 `@InitBinder` 方法来实现。以下是两种常见的方法。
### 方法 1:自定义消息转换器
1. **创建自定义日期反序列化器**:
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 com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @EnableWebMvc public class WebConfig { @Bean public ObjectMapper objectMapper() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.deserializerByType(Date.class, new CustomDateDeserializer()); return builder.build(); } static class CustomDateDeserializer extends JsonDeserializer<Date> { private final SimpleDateFormat format1 = new SimpleDateFormat("yyyy/MM/dd"); private final SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd"); @Override public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String dateStr = p.getText(); try { return format1.parse(dateStr); } catch (ParseException e) { try { return format2.parse(dateStr); } catch (ParseException e1) { throw new IOException("Unparseable date: " + dateStr); } } } } }
### 方法 2:使用 `@InitBinder`
1. **创建控制器并使用 `@InitBinder`**:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @Controller public class MyController { @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Date.class, new CustomDateEditor()); } @PostMapping("/submit") @ResponseBody public String submit(@RequestBody MyData data) { return "Received date: " + data.getDate(); } static class CustomDateEditor extends PropertyEditorSupport { private final SimpleDateFormat format1 = new SimpleDateFormat("yyyy/MM/dd"); private final SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd"); @Override public void setAsText(String text) throws IllegalArgumentException { try { if (text.contains("/")) { setValue(format1.parse(text)); } else { setValue(format2.parse(text)); } } catch (ParseException e) { throw new IllegalArgumentException("Invalid date format"); } } } static class MyData { private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } } }
### 总结
- **自定义消息转换器**:通过定制 `ObjectMapper`,在全局范围内支持多种日期格式。
- **`@InitBinder`**:在控制器中设置自定义日期编辑器,适用于特定的请求处理。
两种方法都可以有效地支持多种日期格式的反序列化,选择适合我们应用场景的方法即可。
添加评论