4

我有以下课程:

public static class ARestRequestParam
{
    String name;
    LocalDate date;  // joda type
}

我希望它从杰克逊处理的以下 JSON 中反序列化。

{名称:“abc”,日期:“20131217”}

实际上,我想反序列化任何具有“yyyyMMdd”格式的类中的任何 LocalDate 字段,而不复制格式字符串,不添加任何 setter 方法,不进行任何 XML 配置。(即注解和Java代码更可取) 怎么做?

另外,我也想知道序列化部分。也就是说,LocalDate -> "yyyyMMdd"。

我看过以下内容:

但我不知道哪个是适用的,哪个是最新的。

顺便说一句,我使用 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");
    }
}
4

1 回答 1

5

你的代码没问题,但如果你@EnableWebMvc在 Spring Boot 应用程序中使用,你会关闭框架中的默认设置,所以也许你应该避免这种情况。此外,现在您的 MVC 处理程序适配器中只有一个 HttpMessageConverter。如果您使用 Spring Boot 的快照,您应该能够简单地定义 a @Beanof 类型Module,其他一切都是自动的,所以我建议您这样做。

于 2013-12-18T10:25:36.843 回答