Hello Im trying to add vavr to my projet, right now Im struggling with proper serializaition of Vavr.List objects. Below is my controller:
import io.vavr.collection.List;
@GetMapping(value = "/xxx")
public List<EntityDeleted> getFile() {
return List.of(new EntityDeleted(true),new EntityDeleted(true),new EntityDeleted(true),new EntityDeleted(true));
}
EntityDeleted is my custom object, List is Vavr collection as shown in import statement. The response Im getting in Postman is:
{
"empty": false,
"lazy": false,
"async": false,
"traversableAgain": true,
"sequential": true,
"singleValued": false,
"distinct": false,
"ordered": false,
"orNull": {
"deleted": true
},
"memoized": false
}
where I expect JSON list of my objects. Below is my config:
@SpringBootApplication
public class PlomberApplication {
public static void main(String[] args) {
SpringApplication.run(PlomberApplication.class, args);
}
@Bean
public ObjectMapper jacksonBuilder() {
ObjectMapper mapper = new ObjectMapper();
return mapper.registerModule(new VavrModule());
}
}
and bit of pom.xml
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr-jackson</artifactId>
<version>0.9.0</version>
</dependency>
Spring Boot retrieves all instances of com.fasterxml.jackson.databind.Module class and initializes ObjectMapper with them. There's no need for additional magic.
My dependencies are as follows (Spring Boot 1.5.7.RELEASE):
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
compile group: 'io.vavr', name: 'vavr', version: '0.9.1'
compile group: 'io.vavr', name: 'vavr-jackson', version: '0.9.1'
}
With application configurured like this:
@SpringBootApplication
public class BootvavrApplication {
public static void main(String[] args) {
SpringApplication.run(BootvavrApplication.class, args);
}
@Bean
Module vavrModule() {
return new VavrModule();
}
}
and controller mapped like this:
import io.vavr.collection.List;
@RestController
class TestController {
@GetMapping("/test")
List<String> testing() {
return List.of("test", "test2");
}
}
output is:
["test","test2"]
You can check the code out here: https://github.com/mihn/bootvavr
I'm not familiar with SpringBoot, but it seems you should return the VavrModule
object instead of the ObjectMapper
in your jacksonBuilder()
method.
I base myself on these links:
https://github.com/vavr-io/vavr/issues/1885#issuecomment-284037353
https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring#jackson-modules
The ObjectMapper
you register as a bean is just not the one being use to serialize into JSON, Spring MVC won't use it to as it's not what he is looking for.
To handle content for HTTP Spring MVC uses HttpMessageConverter and if he detects Jackson in the classpath a MappingJackson2HttpMessageConverter will be autoconfigured if not specified.
In Spring Boot adding should be enough to register the custom MessageConverter:
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new VavrModule());
// Spring MVC default Objectmapper configuration
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
jacksonConverter.setObjectMapper(mapper);
return jacksonConverter;
}
In a pure Spring MVC application you would have to had the following code in the WebMvcConfigurerAdapter
class:
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new VavrModule());
// Spring MVC default Objectmapper configuration
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
jacksonConverter.setObjectMapper(mapper);
return jacksonConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customJackson2HttpMessageConverter());
super.addDefaultHttpMessageConverters();
}
Some Documentation about ObjectMapper in Spring MVC
Hope it helped!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With