Is it possible to create a custom Jackson object object for Spring without resorting to XML?

It's easy to create a custom ObjectMapper for Spring, but XML is required for configuration. I am trying to reduce the amount of XML configuration for things that really won't change without requiring a relocation of my entire system.

So the title says it all - can I use annotations or some other method other than XML to tell Spring: "Hey, please use my custom mapper pls object"?


EDIT:

This does not work

@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: I don't think Spring uses my ObjectMapper. I have this code:

 @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; } 

but when I set a breakpoint on System.out.println("Hi, bob") , it is never called - although I definitely serialize DateTime.

+5
source share
2 answers

You can always follow the steps outlined in Spring Docs .

If you want to completely replace the standard ObjectMapper , define @Bean this type and mark it as @Primary .

Defining a @Bean type Jackson2ObjectMapperBuilder will allow you to configure both standard ObjectMapper and XmlMapper (used in MappingJackson2HttpMessageConverter and MappingJackson2XmlHttpMessageConverter respectively).

So, either you define @Bean using ObjectMapper as follows:

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

Or you define @Bean type Jackson2ObjectMapperBuilder and configure the builder as follows:

 @Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); // Customize builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd")); return builder; } 

This blog post describes the setup further.

To register beans with the @Bean annotation, you must declare @Bean in the @Configuration class, as described in the Spring Java-based container configuration documents .

+3
source

This seems to be a mistake. Spring's download documentation says that annotating an ObjectMapper Bean with @Primary should use the Spring context, not Spring. However, this does not work. I found a workaround without using 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 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); } 
+2
source

Source: https://habr.com/ru/post/1214742/


All Articles