2

I have the following SpringBootApplication:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
@Configuration
public class RestServer implements WebMvcConfigurer {
  public static void main(String[] args) {
    SpringApplication.run(RestServer.class, args);
  }
}

And I would like Guava's Multimap get automatically serialized to JSON.

So I have this code in one of my classes, where all other fields are successfully serialized to JSON:

@JsonProperty("multimap_test")
public Multimap<Instrument, AdjustedLimitOrder> getMultimap() {
  return someMultiMap;
}

But the returned JSON field looks like this:

"multimap_test": {
  "empty": false
}

Do I have to specify a deserializer on the field?

Using this doesn't work because there is no default constructor:

@JsonProperty("multimap_test")
public Multimap<Instrument, AdjustedLimitOrder> getMultimap() {
  return someMultimap;
}

Note that my example is implementing WebMvcConfigurer.

Here is a list of links of instructions that didn't seem conclusive on how to do this, because they discuss the case when the SpringBootApplication implements SpringBootServletInitializer or WebMvcConfigurerAdapter (which is deprecated).

How can Guava's Multimap get automatically serialized?

Neil
  • 24,551
  • 15
  • 60
  • 81

1 Answers1

4

The spring boot MVC auto-configuration already configures to use Jackson to input/output JSON if Jackson is found in classpath. But the configured Jackson by default will not support Guava Multimap, you have to register GuavaModule to the Jackson ObjectMapper in order to support it (see docs).

From the JacksonAutoConfiguration docs , it will auto-register GuavaModule to the ObjectMapper if we declare it as a bean. So in order to serialize/desearialize Multimap , you have to

  1. Add Jackson 's Guava module to pom.xml :

     <dependency>
       <groupId>com.fasterxml.jackson.datatype</groupId>
       <artifactId>jackson-datatype-guava</artifactId>
     </dependency>
    
  2. Declare a GuavaModule bean in @SpringBootApplication :

      @Bean
      public Module guavaModule() {
          return new GuavaModule();
      }
    

And it is done . WebMvcConfigurer / WebMvcConfigurerAdapter is intended for customizing spring boot MVC default settings . You don't need to customize it for your case as Spring MVC already work with Jackson to input/output JSON out of the box . What you need to do is to configure Jackson but not configure spring boot MVC . So, it does not matter whether SpringBootApplication implement or not implement WebMvcConfigurer/WebMvcConfigurerAdapter if you just want to auto-serialise Multimap.

Ken Chan
  • 84,777
  • 26
  • 143
  • 172
  • I added that exact function definition for `public Module guavaModule()` to the `SpringBootApplication`, but IntelliJ IDEA says the function is unused, but it executes when I put a breakpoint on it. However, the `Multimap` just gets serialized as `"multimap_test": { "empty": false }` and no more information. I updated my question with more info. – Neil Feb 01 '19 at 20:59
  • Put the breakpoint at `JacksonAutoConfiguration#configureModules(Jackson2ObjectMapperBuilder builder)` , the `GuavaModule` is registered in here. – Ken Chan Feb 01 '19 at 21:03
  • What is that `@JsonSerialize(using = MultimapSerializer)` ? Try to remove it to see what happen – Ken Chan Feb 01 '19 at 21:06
  • When I put that breakpoint, I can see `GuavaModule@11806` in the `builder.modulesToInstall(moduleBeans.toArray...)` call. And I removed that `@JsonSerialize` annotation, but it's still serializing with only `"empty": false`. – Neil Feb 01 '19 at 21:08
  • I also put breakpoints in all of the `serialize*()` functions in `com.fasterxml.jackson.datatype.guava.ser.MultimapSerializer`, and none of them are triggered. – Neil Feb 01 '19 at 21:10
  • Then not sure. I do not have such problems (I am using the spring boot MVC default settings plus my suggested changes) Can you try to simply put some dummy data to a `Multimap` and then return it ? – Ken Chan Feb 01 '19 at 21:13
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187767/discussion-between-neil-and-ken-chan). – Neil Feb 01 '19 at 21:15