2015-03-05 1 views
5

It's easy to create a custom ObjectMapper Весна, но для конфигурации требуется XML. Я пытаюсь уменьшить количество XML-конфигурации для вещей, которые действительно не будут меняться без необходимости перераспределения всей моей системы.Возможно ли создать пользовательский объект-объект Jackson для Spring, не прибегая к XML?

Таким образом, заголовок говорит все это - могу ли я использовать аннотации или какой-либо другой метод, отличный от XML, чтобы рассказать Spring: «Эй, пожалуйста, используйте мой пользовательский объект mapper pls»?


EDIT:

Это не появляется на работе

@Configuration 
@EnableWebMvc 
public class AppConfig { 

    @Primary 
    @Bean 
    public ObjectMapper mapper(){ 
     ObjectMapper mapper = new ObjectMapper(); 
     mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
     mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); 
     mapper.registerModule(new JodaModule()); 
     mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 
     return mapper; 
    } 
} 

EDIT 2: Я не верю, что весна использует мой ObjectMapper. У меня есть этот код:

@Primary 
@Bean 
public ObjectMapper mapper(){ 
    ObjectMapper mapper = new ObjectMapper(); 
    JodaModule mod = new JodaModule(); 
    mod.addSerializer(DateTime.class, new JsonSerializer<DateTime>() { 
     @Override 
     public void serialize(DateTime dateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 
      System.out.println("Hi, bob"); 
     } 
    }); 
    mapper.registerModule(mod); 

    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
    mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); 
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 
    mapper.enable(SerializationFeature.INDENT_OUTPUT); 

    return mapper; 
} 

но когда я поставил точку останова на System.out.println("Hi, bob") он никогда не называют - Хотя я определенно сериализации DateTime.

+0

Просто создайте и зарегистрируйте его как фасоль? – chrylis

+0

@chrylis, как бы я это сделал? –

ответ

3

Вы всегда можете выполнить шаги, указанные в Spring Docs.

Если вы хотите полностью заменить по умолчанию ObjectMapper, определить @Bean этого типа и пометить его как @Primary.

Определение @Bean типа Jackson2ObjectMapperBuilder позволит вам настроить как по умолчанию ObjectMapper и XmlMapper (используется в MappingJackson2HttpMessageConverter и MappingJackson2XmlHttpMessageConverter соответственно).

Итак, либо вы определяете @Bean с вашими ObjectMapper так:

@Primary 
@Bean 
public ObjectMapper mapper() { 
    // Customize... 
    return new ObjectMapper().setLocale(Locale.UK); 
} 

Или вы определяете @Bean типа Jackson2ObjectMapperBuilder и настроить построитель так:

@Bean 
public Jackson2ObjectMapperBuilder jacksonBuilder() { 
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); 

    // Customize 
    builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd")); 
    return builder; 
} 

This blog entry далее описывает настройку.

Для того, чтобы зарегистрировать бобы с помощью @Bean аннотацию вы должны объявить @Bean в @Configuration классе, как описано в Spring docs about Java-based container configuration.

+0

Я добавил информацию к своему вопросу - я использую первый пример, но он не работает. Имена camelCase не изменяются на 'camel_case' и оба' java.util.Date' и joda 'DateTime' отображаются обычным способом. –

+0

Отказывается ли ваш @ Configuration-класс при запуске? – wassgren

+0

Мне пришлось добавить несколько строк конфигурации в мой web.xml - в моем классе @Configuration и добавлен '@ComponentScan (basePackages =' com.mystuff') '. Он не загружал страницу раньше, но теперь это происходит, поэтому я предполагаю, что она сканируется. –

2

Это, кажется, ошибка. В документации Spring Boot говорится, что аннотация компонента ObjectMapper Bean с помощью @Primary должна использовать контекст Spring вместо его компоновщика по умолчанию Spring. Однако это не работает. Я нашел обходное решение без использования XML.

//Since Spring won't use the custom object mapper Bean defined below for 
//HTTP message conversion(eg., when a Java object is returned from a controller, 
//and should be converted to json using Jackson), we must override this method 
//and tell it to use a custom message converter. We configure that custom converter 
//below to use our customized Object mapper. 
@Override 
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
    converters.add(mappingJackson2HttpMessageConverter()); 
} 

//configures the converter to use our custom ObjectMapper 
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { 
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); 
    //this line here 
    jsonConverter.setObjectMapper(objectMapper()); 
    return jsonConverter; 
} 


//Primary annotation tells the Spring container to use this 
//mapper as the primary mapper, instead of 
//the Spring's defaultly configured mapper. Primary annotation 
// DOESN'T work for some reason(this is most likely a bug and will be resolved in the future. 
// When resolved, this Bean will be all it takes to tell Spring to use this ObjectMapper everywhere) 
// That means that there won't be a need to configure the Http message converters manually(see method above). 
@Primary 
@Bean 
public ObjectMapper objectMapper() { 
    ObjectMapper mapper = new ObjectMapper(); 
    configureObjectMapper(mapper); 
    return mapper; 
} 

//configure ObjectMapper any way you'd like 
//This configuration tells the ObjectMapper to 
//(de)serialize all fields(private,protected,public,..) of all objects 
//and to NOT (de)serialize any properties(getters,setters). 
private void configureObjectMapper(ObjectMapper mapper) { 
    //properties for jackson are fields with getters and setters 
    //sets all properties to NOT be serialized or deserialized 
    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); 
    //tell the mapper to traverse all fields and not only default 
    //default=public fields + fields with getters and setters 
    //set all fields to be serialized and deserialized 
    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); 
} 
Смежные вопросы