У меня есть следующий класс:Spring + Jackson + joda: как определить формат сериализации/десериализации?
public static class ARestRequestParam
{
String name;
LocalDate date; // joda type
}
И я хочу, чтобы это было десериализации из следующего JSON, который обрабатывается Джексоном.
{имя: «а», дата: «20131217»}
На самом деле, я хочу, чтобы десериализации любого поля LocalDate в любом классе с форматом «YYyyMmDd», без дублирования строки формата, без добавления какого-либо метод установки , без какой-либо конфигурации XML. (То есть, примечание и код Java предпочтительны) Как это можно сделать?
Кроме того, я также хочу знать сериализацию. то есть LocalDate -> "yyyyMMdd".
Я видел нижеуказанных:
- ДЖЕКСОНА-тип_данных-Joda (https://github.com/FasterXML/jackson-datatype-joda)
- пользовательских сериализатор (открытый класс JodaDateTimeJsonSerializer расширяет JsonSerializer {...} - Spring @ResponseBody Jackson JsonSerializer with JodaTime)
- @JsonCreator
- @DateTimeFormat
Но я не знаю, и который является самым современным.
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");
}
}
спасибо. На самом деле мне пришлось добавить addResourceHandlers() в класс WebMvcConfiguration для обслуживания статических файлов (поскольку настройки по умолчанию не были). Но поскольку я переопределял addInterceptors(), чтобы добавить перехватчики URL, мне пришлось создать свой собственный класс с EnableWebMvc. – zeodtr
Также, пожалуйста, просмотрите мое обновление и дайте мне какое-нибудь предложение. – zeodtr
Вам не нужно '@ EnableWebMvc' для добавления перехватчиков, просто добавьте' @ Bean' типа 'WebMvcConfigurerAdapter' (стандартная функция Spring MVC). Прочтите ответ: «используйте снимок». Это должно вас разобраться. –