2013-12-18 3 views
3

У меня есть следующий класс:Spring + Jackson + joda: как определить формат сериализации/десериализации?

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

И я хочу, чтобы это было десериализации из следующего JSON, который обрабатывается Джексоном.

{имя: «а», дата: «20131217»}

На самом деле, я хочу, чтобы десериализации любого поля LocalDate в любом классе с форматом «YYyyMmDd», без дублирования строки формата, без добавления какого-либо метод установки , без какой-либо конфигурации XML. (То есть, примечание и код Java предпочтительны) Как это можно сделать?

Кроме того, я также хочу знать сериализацию. то есть LocalDate -> "yyyyMMdd".

Я видел нижеуказанных:

Но я не знаю, и который является самым современным.

BTW, я использую 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"); 
     } 
    } 
} 

Я должен был реализации этой десериализатор себя, так как формат даты и времени для десериализации в Джексоне-типа данных-Joda не может быть изменен. Итак, поскольку я сам реализовал десериализатор, джексон-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

Final рабочая версия выглядит следующим образом: (с другими конфигурациями я сделал ранее в классе, который был @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

Ваш код в порядке, но если вы используете @EnableWebMvc в приложении Spring загрузки вы выключаете настройки по умолчанию в рамках, так что, возможно, вы должны избежать этого. Кроме того, теперь у вас есть только одинHttpMessageConverter в вашем адаптере-манипуляторе MVC. Если вы используете снимок Spring Boot, вы должны просто определить @Bean типа Module, и все остальное будет автоматически, поэтому я бы рекомендовал сделать это таким образом.

+0

спасибо. На самом деле мне пришлось добавить addResourceHandlers() в класс WebMvcConfiguration для обслуживания статических файлов (поскольку настройки по умолчанию не были). Но поскольку я переопределял addInterceptors(), чтобы добавить перехватчики URL, мне пришлось создать свой собственный класс с EnableWebMvc. – zeodtr

+0

Также, пожалуйста, просмотрите мое обновление и дайте мне какое-нибудь предложение. – zeodtr

+0

Вам не нужно '@ EnableWebMvc' для добавления перехватчиков, просто добавьте' @ Bean' типа 'WebMvcConfigurerAdapter' (стандартная функция Spring MVC). Прочтите ответ: «используйте снимок». Это должно вас разобраться. –

Смежные вопросы