我有以下课程:
public static class ARestRequestParam
{
String name;
LocalDate date; // joda type
}
我希望它从杰克逊处理的以下 JSON 中反序列化。
{名称:“abc”,日期:“20131217”}
实际上,我想反序列化任何具有“yyyyMMdd”格式的类中的任何 LocalDate 字段,而不复制格式字符串,不添加任何 setter 方法,不进行任何 XML 配置。(即注解和Java代码更可取) 怎么做?
另外,我也想知道序列化部分。也就是说,LocalDate -> "yyyyMMdd"。
我看过以下内容:
- 杰克逊数据类型乔达(https://github.com/FasterXML/jackson-datatype-joda)
- 自定义序列化器(公共类 JodaDateTimeJsonSerializer 扩展 JsonSerializer { ... } - Spring @ResponseBody Jackson JsonSerializer with JodaTime)
- @JsonCreator
- @日期时间格式
但我不知道哪个是适用的,哪个是最新的。
顺便说一句,我使用 Spring Boot。
更新
好的,我已经设法为反序列化部分编写了工作代码。如下:
@Configuration
@EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter
{
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters)
{
converters.add(jacksonConverter());
}
@Bean
public MappingJackson2HttpMessageConverter jacksonConverter()
{
MappingJackson2HttpMessageConverter converter =
new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ApiJodaModule());
converter.setObjectMapper(mapper);
return converter;
}
@SuppressWarnings("serial")
private class ApiJodaModule extends SimpleModule
{
public ApiJodaModule()
{
addDeserializer(LocalDate.class, new ApiLocalDateDeserializer());
}
}
@SuppressWarnings("serial")
private static class ApiLocalDateDeserializer
extends StdScalarDeserializer<LocalDate>
{
private static DateTimeFormatter formatter =
DateTimeFormat.forPattern("yyyyMMdd");
public ApiLocalDateDeserializer() { super(LocalDate.class); }
@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (jp.getCurrentToken() == JsonToken.VALUE_STRING)
{
String s = jp.getText().trim();
if (s.length() == 0)
return null;
return LocalDate.parse(s, formatter);
}
throw ctxt.wrongTokenException(jp, JsonToken.NOT_AVAILABLE,
"expected JSON Array, String or Number");
}
}
}
我必须自己实现反序列化器,因为无法更改 jackson-datatype-joda 中反序列化器的日期时间格式。因此,由于我自己实现了反序列化器,因此不需要 jackson-datatype-joda。(虽然我已经复制了它的部分代码)
这段代码好吗?
这是最新的解决方案吗?
还有其他更简单的方法吗?
任何建议将不胜感激。
更新
按照 Dave Syer 的建议,我将上面的源代码修改如下:
删除了 2 个方法:configureMessageConverters()、jacksonConverter()
在 WebMvcConfiguration 类中添加了以下方法:
@Bean
public Module apiJodaModule()
{
return new ApiJodaModule();
}
但现在它不起作用。似乎 apiJodaModule() 被忽略了。
我怎样才能让它工作?
(看来我不应该有一个具有 @EnableWebMvc 的类来使用该功能。)
我使用的版本是 org.springframework.boot:spring-boot-starter-web:0.5.0.M6。
更新
最终工作版本如下:(与我之前在具有@EnableWebMvc 的课程中完成的其他配置)
正如 Dave Syer 所提到的,这仅适用于 BUILD-SNAPSHOT 版本,至少目前如此。
@Configuration
public class WebMvcConfiguration
{
@Bean
public WebMvcConfigurerAdapter apiWebMvcConfiguration()
{
return new ApiWebMvcConfiguration();
}
@Bean
public UserInterceptor userInterceptor()
{
return new UserInterceptor();
}
public class ApiWebMvcConfiguration extends WebMvcConfigurerAdapter
{
@Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(userInterceptor())
.addPathPatterns("/api/user/**");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
}
@Bean
public Module apiJodaModule()
{
return new ApiJodaModule();
}
@SuppressWarnings("serial")
private static class ApiJodaModule extends SimpleModule
{
public ApiJodaModule()
{
addDeserializer(LocalDate.class, new ApiLocalDateDeserializer());
}
private static final class ApiLocalDateDeserializer
extends StdScalarDeserializer<LocalDate>
{
public ApiLocalDateDeserializer() { super(LocalDate.class); }
@Override
public LocalDate deserialize(JsonParser jp,
DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (jp.getCurrentToken() == JsonToken.VALUE_STRING)
{
String s = jp.getText().trim();
if (s.length() == 0)
return null;
return LocalDate.parse(s, localDateFormatter);
}
throw ctxt.mappingException(LocalDate.class);
}
}
private static DateTimeFormatter localDateFormatter =
DateTimeFormat.forPattern("yyyyMMdd");
}
}