Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Jackson with composition over inheritance

I'm trying to use Jackson to manage the types for me, but instead of using inheritance for types creation I want to use composition and have a set of factory methods with some annotation that will instruct Jackson what types these are. Concrete example:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public interface MyInterface {
    void doStuff();

    // Factories

    @JsonCreator
    @JsonSubTypes.Type(value = MyInterface.class, name = "impl1")
    static MyInterface impl1() {
        return new MyInterfaceWithComposition(() -> System.out.println("Impl1"));
    }

    @JsonCreator
    @JsonSubTypes.Type(value = MyInterface.class, name = "impl2")
    static MyInterface impl2() {
        return new MyInterfaceWithComposition(() -> System.out.println("Impl2"));
    }
}

public class MyInterfaceWithComposition implements MyInterface {
    private final Runnable task;

    public MyInterfaceWithComposition(Runnable task) {
        this.task = task;
    }

    @Override
    public void doStuff() {
        task.run();
    }
}

I know I can create a custom serializer/deserializer, but I was hoping there's a way to avoid it and make Jackson do all the work.

It feels to me like it shouldn't be this hard to do this. Am I missing some Jackson trick/annotation? I'd appreciate your help.

like image 214
Artur Avatar asked Nov 22 '22 01:11

Artur


1 Answers

@JsonUnwrapped can be used for composition.

Serialization for Person

    public class Person {
      public int age;
      @JsonUnwrapped
      public Name name;
    }

produces the following JSON.

    {
      "age" : 18,
      "first" : "John",
      "last" : "Doe"
    }

References:

  • https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.12.3/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java#L168
like image 144
Riku J.K. Avatar answered Nov 26 '22 10:11

Riku J.K.