Search code examples
jacksonimmutables-library

Immutables wrapper as string in Jackson


How can I jackson serialize a wrapper type to and from a string?

I merged the following from two different examples their website. But the HostName type is serialized/deserialized as

{ "name" : "my.host.name.com" }

when I want it to be simply the string

"my.host.name.com"

Note that I have a lot of XName types, hence the use of the Immutables wrapper. So I would prefer a solution that keeps the amount of boiler plate down.


@Value.Immutable @AbstractName.Wrapper
public abstract class _HostName extends AbstractName { }

...

public abstract class AbstractName {

    @JsonSerialize
    @JsonDeserialize
    @Value.Style(
        // Detect names starting with underscore
        typeAbstract = "_*",
        // Generate without any suffix, just raw detected name
        typeImmutable = "*",
        // Make generated public, leave underscored as package private
        visibility = Value.Style.ImplementationVisibility.PUBLIC,
        // Seems unnecessary to have builder or superfluous copy method
        defaults = @Value.Immutable(builder = false, copy = false))
    public @interface Wrapper {}




    @Value.Parameter
    public abstract String name();

    @Override
    public String toString() { return name(); }
}

Solution

  • I've got this to work like below. There's an extra annotation on my name types. It's not my favorite, but it works.

    @JsonDeserialize(as=HostName.class)
    @Value.Immutable @AbstractName.Wrapper
    public abstract class _HostName extends AbstractName { }
    
    ...
    
    public abstract class AbstractName {
    
        @Value.Style(
            // Detect names starting with underscore
            typeAbstract = "_*",
            // Generate without any suffix, just raw detected name
            typeImmutable = "*",
            // Make generated public, leave underscored as package private
            visibility = Value.Style.ImplementationVisibility.PUBLIC,
            // Seems unnecessary to have builder or superfluous copy method
            defaults = @Value.Immutable(builder = false, copy = false))
        public @interface Wrapper {}
    
    
        @JsonValue
        @Value.Parameter
        public abstract String name();
    
        @Override
        public String toString() { return name(); }
    }
    

    Here's a little program to run it:

    public static void main(String... args) throws IOException {
        ObjectMapper json = new ObjectMapper();
    
        String text = json.writeValueAsString(HostName.of("my.host.name.com"));
    
        System.out.println(text);
    
        HostName hostName = json.readValue(text, HostName.class);
        System.out.println(hostName);
    }