Jackson lista nula para serialización de matriz vacía

Aug 19 2020

Quiero serializar la lista nula en una matriz vacía.

Así dado:

class MyBean { List values; }

Y dada una instancia con valores nulos, debe serializarse para:

{ "values": [] }

Quiero que este sea un comportamiento global para todas las listas en todas las clases. No quiero agregar anotaciones o manejo específico para clases.

He leído todas las preguntas relacionadas que encontré y no pude encontrar nada que funcione. Parece que cualquier serializador personalizado que intento registrar para la clase List no está funcionando.

Si tiene esto funcionando en su proyecto, avíseme cómo se las arregló para hacerlo.

Respuestas

2 MichałZiober Aug 19 2020 at 09:48

En casos como este, debes personalizar la JacksonAnnotationIntrospectorclase. Te serialize null-s, por defecto, Jacksonusa com.fasterxml.jackson.databind.ser.std.NullSerializerclass. Puede extender la clase de introspector predeterminada y anular findNullSerializer.

Vea el siguiente ejemplo:

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;
    }
}

Impresiones del código anterior:

{"values":[]}