Search code examples
jsonlistserializationjacksonobjectmapper

Jackson Serializer called on wrong types


I'm working with Jackson and I've written the following custom serializer:

public class FooSerializer extends StdSerializer<List<Foo>> {

  public FooSerializer() {
    this(null);
  }

  public FooSerializer(Class<List<Foo>> t) {
    super(t);
  }

  public void serialize(List<Foo> foos, JsonGenerator gen, SerializerProvider provider) throws IOException {
    gen.writeStartArray(foos.size());
    for(Foo foo : foos){
        gen.writeString(foo.getName());
    }
    gen.writeEndArray();
  }
}

I have registered it in the ObjectMapper as follows:

SimpleModule fooModule = new SimpleModule("Foo Module");
fooModule.addSerializer(new FooSerializer((Class<List<Foo>>)(Object)List.class));
objectMapper.registerModule(fooModule);

I'm expecting it to take an object holding a List of Foos and return it like

{
  ...
  "foos":["name1", "name2"]
  ...
}

This works fine, however, when I'm passing a List of SomeObjectHoldingFoos, each holding a List of Foo, the ObjectMapper tries to apply the FooSerializer to this List already, resulting in the Foo cannot be cast to SomeObjectHoldingFoos Exception.

I'm suspecting that the handledType of the FooSerializer somehow was set as List instead of List<Foo> but I don't know how to fix that, since there seems to be no class for a paramerized type.

What can I do?


Solution

  • Use JavaType instead of Class.

    class FooSerializer extends StdSerializer<List<Foo>> {
    
        FooSerializer(JavaType javaType) {
            super(javaType);
        }
    
        ....
    }
    

    And register it like below:

    SimpleModule fooModule = new SimpleModule("Foo Module");
    CollectionLikeType type = mapper.getTypeFactory().constructCollectionLikeType(ArrayList.class, Foo.class);
    fooModule.addSerializer(new FooSerializer(type));