Skip to content
Advertisement

Can’t register Gson TypeAdapter in Spring Boot

I have been trying to add custom serialization of my Version class in RestComponent:

public class Version {
    public int MAJOR;
    public int MINOR;
    public int REVISION;
    public Integer BUILD;
}

Json output I expect:

"1.2.2"

not

{
  "MAJOR": 1,
  "MINOR": 2,
  "REVISION": 2,
  "BUILD": null
}

So I decide to use JsonSerializer and JsonDeserializer interfaces, also tried TypeAdapter. I’ve created a Gson Bean in my MVC configuration class, also tried to create GsonBuilder bean. In application properties I choosen gson as serializator, and removed Jackson dependencies.

@Bean
public Gson gson() {
    var strategy = new ExclusionStrategy() {
        
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            return f.getAnnotation(GsonExclude.class) != null;
        }
            
        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }
    };
        
    return new GsonBuilder()
            .registerTypeHierarchyAdapter(Version.class, new VersionGsonAdapter())
            .addSerializationExclusionStrategy(strategy)
            .addDeserializationExclusionStrategy(strategy)
            .disableHtmlEscaping()
            .serializeNulls()
            .setPrettyPrinting()
            .create();
}

All other settings as Exlusion strategies and pretty printing is working fine, but type adpapters – not.

I also tried to configure message converters (configureMessageConverters, extendMessageConverters):

@Configuration
public class WebMVCConfig implements WebMvcConfigurer  {
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.removeIf(c -> c instanceof GsonHttpMessageConverter);
        converters.add(new GsonHttpMessageConverter(gson()));
    }
}

Advertisement

Answer

As explained in the reference documentation, you can customize the Gson infrastructure with a GsonBuilderCustomizer like so:

@Configuration
public class GsonConfiguration {

    @Bean
    public GsonBuilderCustomizer typeAdapterRegistration() {
        return builder -> {
            builder.registerTypeAdapter(Version.class, new VersionTypeAdapter());
        };
    }
}

Please make sure that you’ve set Gson as your preferred JSON library, as Jackson is often brought transitively by many dependencies. In application.properties, you can add the following:

spring.mvc.converters.preferred-json-mapper=gson

I’ve successfully tested this approach with the following controller:

@RestController
public class GsonController {

    @GetMapping("/version")
    public Version showVersion() {
        return Version.fromVersionString("1.2.3-42");
    }
}

The controller returns:

➜  ~ http :8080/version
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/json;charset=UTF-8
Keep-Alive: timeout=60
Transfer-Encoding: chunked

"1.2.3-42"
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement