4

I have a class like this:

class MyClass {
    CustomList<String> list = ListUtils.createCustomList();
}

Where interface CustomList implements java.util.List so it cannot be deserialized with a constructor. Instead there is a class ListUtils which creates an implementation instance. Both the interface and the utility class are in an external library so I can't annotate them.

How can I tell Jackson that when encountering CustomList it should invoke ListUtils.createCustomList() instead of a constructor? Is there a mixin configuration, a mapping I can specify from type to construction method, or a custom deserializer I need to write?

Mark
  • 2,167
  • 4
  • 32
  • 64

1 Answers1

2

You have 2 issues here, the first of which is how to tell Jackson to use a static method of another class ListUtils to create an instance of CustomList class. There is @JsonCreator that you could use on a static method of CustomList or through a mix in. Unfortunately, you can't use that on ListUtils. There is a an open issue for that.

Until the above request is implemented / released you have to create a custom deserializer. A skeleton implementation of such a deserializer would look something like this:

class ListDeserializer extends JsonDeserializer<CustomList> {
    @Override
    public CustomList deserialize(JsonParser p, DeserializationContext c) throws IOException {
        return ListUtils.createCustomList();
    }
}

Extend this method with other initialization steps, e.g. to parse elements with JsonParser and add them to the list before returning it. See an example here. You can specify this deserializer to be used without any annotations on the ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(CustomList.class, new ListDeserializer());
mapper.registerModule(module);
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
  • Thanks. About populating the list after construction, can't I tell Jackson to just populate the list as it would anyway? All I want to change is the initialization step and then continue as usual. – Mark Nov 26 '17 at 19:37
  • Found the answer I was looking for and marked as duplicate, but this answer is correct anyway. – Mark Nov 27 '17 at 12:59