Configuring Jackson ObjectMapper via Grail bean DSL

I need a generic instance of com.fasterxml.jackson.databind.ObjectMapper in grails, so I think the most standard way to do this is through DSL beans. I tried something like (with many options, e.g. using the delegate keyword) in resources.groovy

objectMapper(ObjectMapper) { bean -> bean.setVisibility(PropertyAccessor.ALL, Visibility.ANY) bean.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) } 

but this did not work, ObjectMapper is configured by default, which works poorly with grails. I used a workaround that does what I need (in BootStrap.groovy):

 def init = { servletContext -> def bean = Holders.applicationContext.objectMapper bean.setVisibility(PropertyAccessor.ALL, Visibility.ANY) bean.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) } 

Can someone tell me how to do this in beans DSL where it belongs (IMHO)?

+4
source share
3 answers

The bean closure parameter type has some subtype of AbstractBeanDefinition , it does not apply to the actual instance of the object.

There are various ways to configure visibility and customize an instance of ObjectMapper:

You can use all Spring IoC container mechanisms to create beans in Grails.

Not that I had this particular use case, but I would like to create a custom factory bean and put the logic there for the ObjectMapper configuration.

+1
source

Provide JsonFactory in the constructor instead of using the default constructor.

 //resources.groovy beans = { jf(com.fasterxml.jackson.core.JsonFactory) objectMapper(ObjectMapper, jf){ visibility(PropertyAccessor.ALL, Visibility.ANY) configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) } } 

This can be checked in the console as:

 assert grailsApplication.mainContext.objectMapper instanceof com.fasterxml.jackson.databind.ObjectMapper 
+1
source

For the visibility bit, you can set VisibilityChecker instead of using the convenience method setVisibility

 vc(VisibilityChecker.Std, Visibility.ANY) objectMapper(ObjectMapper) { visibilityChecker = ref('vc') } 

but the configure call is more complicated, you will need to use the factory bean approach to call the method, defining a separate bean. The fact is that you do not want to call methods yourself, and you are trying to tell Spring that he needs to call when he wants to create beans:

 objectMapperConfig(objectMapper:'configure', DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 

Since configure returns a reference to the translator itself, the best way to ensure that the dependencies are resolved in the correct order might be to say

 vc(VisibilityChecker.Std, Visibility.ANY) objectMapperUnconfigured(ObjectMapper) { visibilityChecker = ref('vc') } objectMapper(objectMapperUnconfigured:'configure', DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 

and then use objectMapper as the bean that you enter elsewhere.

+1
source

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


All Articles