Lista nula de Jackson para serialização de array vazio

Aug 19 2020

Eu quero serializar a Lista nula em uma matriz vazia.

Dado assim:

class MyBean { List values; }

E dada uma instância com nulo para valores, ele deve ser serializado para:

{ "values": [] }

Quero que seja um comportamento global para todas as listas em todas as classes. Não quero adicionar anotações ou tratamento específico para as classes.

Eu li todas as perguntas relacionadas que encontrei e não encontrei nada que funcionasse. Parece que qualquer serializador personalizado que tento registrar para a classe List não está funcionando.

Se você tem isso funcionando em seu projeto, diga-me como você conseguiu fazer isso.

Respostas

2 MichałZiober Aug 19 2020 at 09:48

Em casos como esse, você precisa personalizar a JacksonAnnotationIntrospectorclasse. Te serialize null-s, por padrão, Jacksonusa com.fasterxml.jackson.databind.ser.std.NullSerializerclass. Você pode estender a classe padrão do introspector e substituir findNullSerializer.

Veja o exemplo abaixo:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;
import java.util.List;

public class Main {

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(new EmptyArrayJacksonAnnotationIntrospector());
        mapper.writeValue(System.out, new ListWrapper());
    }
}

class EmptyArrayJacksonAnnotationIntrospector extends JacksonAnnotationIntrospector {

    @Override
    public Object findNullSerializer(Annotated a) {
        if (List.class.isAssignableFrom(a.getRawType())) {
            return ArrayNullSerializer.INSTANCE;
        }
        return super.findNullSerializer(a);
    }
}

final class ArrayNullSerializer extends StdSerializer<Object> {

    public static final ArrayNullSerializer INSTANCE = new ArrayNullSerializer();

    protected ArrayNullSerializer() {
        super(Object.class);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartArray();
        gen.writeEndArray();
    }
}

class ListWrapper {

    private List values;

    public List getValues() {
        return values;
    }

    public void setValues(List values) {
        this.values = values;
    }
}

Impressões de código acima:

{"values":[]}