2013-12-18 42 views
3

我有以下類:Spring + Jackson + joda time:如何指定序列化/反序列化格式?

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

而且我希望它從由傑克遜處理以下JSON反序列化。

{名:「ABC」,日期:「20131217」}

其實,我想反序列化與「年月日」的格式,任何類中的任何LOCALDATE的領域,而不用複製格式字符串,不添加任何setter方法,沒有任何XML配置。 (也就是說,註釋和Java代碼是最好的) 怎麼做?

另外,我也想知道序列化部分。即LocalDate - >「yyyyMMdd」。

我見過如下:

但我不知道哪個是appl可用的,並且是最新的。

順便說一句,我使用Spring Boot。

UPDATE

好吧,我已經成功地寫反序列化部分的工作代碼。 它如下:

@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。 (雖然我已經複製了它的代碼)

這個代碼還可以嗎?
這是最新的解決方案嗎?
還有其他更簡單的方法嗎?
任何建議將不勝感激。

UPDATE

繼戴夫Syer的建議,我修改了源上方如下:

刪除2種方法:configureMessageConverters(),jacksonConverter()
添加以下的方法進WebMvcConfiguration類:

@Bean 
public Module apiJodaModule() 
{ 
    return new ApiJodaModule(); 
} 

但現在它不起作用。看起來apiJodaModule()被忽略。
我該如何使它工作?
(看來我不應該有@EnableWebMvc使用該功能的類。)

我使用的版本是org.springframework.boot:彈簧引導起動網:0.5.0.M6 。

UPDATE

最終工作的版本如下:
戴維Syer提到的,這隻會在BUILD-SNAPSHOT工作(在其他配置我以前在有@EnableWebMvc類已完成)版本,至少現在。

@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

你的代碼是好的,但如果你在Spring啓動應用程序中使用@EnableWebMvc您在框架關閉的默認設置,那麼也許你應該避免這種情況。另外,您現在在您的MVC處理程序適配器中只有一個HttpMessageConverter。如果你使用Spring Boot的快照,你應該能夠簡單地定義的Module類型,其他的都是自動的,所以我建議你這樣做。

+0

謝謝。實際上,我必須將addResourceHandlers()添加到WebMvcConfiguration類才能提供靜態文件(因爲默認設置已消失)。但是因爲我重寫了addInterceptors()來添加URL攔截器,所以我不得不創建自己的具有EnableWebMvc的類。 – zeodtr

+0

另請查看我的更新並給我一些建議。 – zeodtr

+0

爲了添加攔截器,您不需要'@ EnableWebMvc',只需添加類型爲「WebMvcConfigurerAdapter」(標準Spring MVC功能)的'@ Bean'。閱讀答案:「使用快照」。這應該把你排除在外。 –

相關問題