javajacksonimmutables-library

Jackson serialization of immutable value class with optional fields


I am using Immutables library (https://immutables.github.io).

My class looks as follows:

package com.abc.myservice.data.models;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;

import java.util.Map;
import java.util.Optional;

@Value.Immutable
@JsonSerialize(as = ImmutableMyEntityModel.class)
@JsonDeserialize(as = ImmutableMyEntityModel.class)
public interface MyEntityModel {
    String myEntityId();
    String status();
    Optional<Integer> count();
    Optional<Integer> version();
    Optional<Map<String, String>> attributes();
}

I build the immutable class object with:

ImmutableMyEntityModel.builder()
    .myEntityId("some-id")
    .status("some-status")
    .count(Optional.of(10))
    .build()

And my output is:

{
    "MyEntityId": "some-id",
    "status": "some-status",
    "count": {
        "present": true
    },
    "version": {
        "present": false
    },
    "attributes": {
        "present": false
    }
}

Instead what I would like to see is:

{
    "MyEntityId": "some-id",
    "status": "some-status",
    "count": 10
}

How can I make it work like that?


Solution

  • Use the jackson-datatype-jdk8 module so that Jackson properly understands the java.util.Optional type - a pretty good explanation is in this article.


    ObjectMapper om = new ObjectMapper();
    om.registerModule(new Jdk8Module());
    

    Full example:

    public class JacksonOptionalTest
    {
        public static void main(String... args)
        throws Exception
        {
            ObjectMapper om = new ObjectMapper();
            om.registerModule(new Jdk8Module());
    
            Thing thing = new Thing();
            thing.name = "John Smith";
            thing.count = Optional.of(12);
    
            String s = om.writeValueAsString(thing);
            System.out.println(s);
        }
    
        @JsonInclude(Include.NON_ABSENT)
        @JsonIgnoreProperties(ignoreUnknown = true)
        public static class Thing
        {
            public String name;
            public Optional<Integer> count = Optional.empty();
            public Optional<Integer> version = Optional.empty();
        }
    }
    

    The output of this is {"name":"John Smith","count":12}.