Search code examples
javaspring-bootjacksonimmutables-library

Cannot partially deserialize JSON into Immutables object with spring boot


I have a JSON file that I read via restTemplate and want to store only certain fields in to my object. The call is successfull but my object does not contain the informations from the JSON. This is the file and I am only interested in the my-channels object.

my pom.xml:

<!-- SNIP standard stuff generated by start.spring.io -->
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jdk8</artifactId>
            <version>2.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.immutables</groupId>
            <artifactId>value</artifactId>
            <version>2.5.6</version>
            <scope>provided</scope>
        </dependency>

my JacksonConfig that disables failing on missing fields and has kebab-case enabled:

@Configuration
public class JacksonConfig {
    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        final ObjectMapper objectMapper = new ObjectMapper();

        objectMapper.registerModule(new Jdk8Module());

        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);

        return objectMapper;
    }
}

The object to hold my data.

@Value.Immutable
@JsonSerialize(as = com.example.demo.ImmutableGist.class)
@JsonDeserialize(as = com.example.demo.ImmutableGist.class)
public interface AbstractGist {
    List<ImmutableMyChannels> myChannels();

    @Value.Immutable
    @JsonSerialize(as = ImmutableMyChannels.class)
    @JsonDeserialize(as = ImmutableMyChannels.class)
    interface AbstractMyChannels {
        String channelId();

        String locale();
    }
}

and my main with the commandlinerunner:

@SpringBootApplication
public class DemoApplication {

    private static final String URL = "https://rawgit.com/Gregsen/936f0dc5f1a83687ada6b64a0fe20a0c/raw/1ee44d3e7aa94851a811108b2606e803f8734c8d/example.json";
    private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }


    @Bean
    public CommandLineRunner run() throws Exception {
        RestTemplate restTemplate = new RestTemplate();
        return args -> {
            ImmutableGist gist = restTemplate.getForObject(URL, ImmutableGist.class);

            log.info(gist.toString());
        };
    }
}

The application compiles and runs, the output, however, is simply Gist{salesChannels=[]} (minus the whole spring default output)


Solution

  • So, after some more fiddling around and reading, it seems, the issue can be resolved as such:

    instead of using @JsonDeserialize(as = ImmutableMyChannels.class) one should use the builder, that is also generated.

    @JsonDeserialize(builder = ImmutableMyChannels.Builder.class).