setSerializationInclusion(Include.NON_EMPTY) not excluding Nulls in arrays

Viewed 1959

I've tested a few ways to remove Null values in my java object from my output file (Json). However, there seems to be some that are missed. I'm using 2.9.6

I've tried the following:

objectMapper.setSerializationInclusion(Include.NON_NULL);
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
@JsonInclude(Include.NON_NULL);

Here is my code:

  public static String convertToJson(Hospital patient) {
    try {
      if (patient != null) {
        String json = objectMapper.writeValueAsString(patient);
        return json;
      }
    } catch (IOException e) {
      throw new RuntimeException("Error converting person to Json " + e);
    }
    return null;
  }

These have removed around 2150 nulls from the output file. However, the results still have some that are present in the form of:

"patient" : {
    "corporateEntityCode" : "OH",
    "groupNumber" : "123ABCD",
    "patientIdentifier" : 12345678,
    "patientPreexistingDiagnosticCode" : [ null, null, null, null, null, null ],
    "patientPreexistingEffectiveDate" : [ null, null, null, null, null, null ],
    "patientSubscriptNumber" : "01",
    "subscriberNumber" : "0000000123456789"
}

Is this an existing issue? Or have I not implemented this correctly?

1 Answers

It doesn't seem like an existing issue in the library but it is surprising that when using Include.NON_NULL it has an impact on Map, ignoring pairs where the value is null but it does not have any impact on Array or Collection. Anyway, you can achieve what you want quite easily with a custom serializer. I've created a different model just to show you how to do it. The example covers the custom serialization of Arrays and any class that extends Collection.

Model class Hospital:

public class Hospital {
    private List<String> patients;
    private String[] doctors;

    public List<String> getPatients() {
        return patients;
    }

    public void setPatients(List<String> patients) {
        this.patients = patients;
    }

    public String[] getDoctors() {
        return doctors;
    }

    public void setDoctors(String[] doctors) {
        this.doctors = doctors;
    }
}

Custom serializer to ignore null values in classes that extend Collection:

 class CollectionIgnoreNullSerializer extends StdSerializer<Collection> {
    public CollectionIgnoreNullSerializer() {
        this(null);
    }

    public CollectionIgnoreNullSerializer(Class<Collection> t) {
        super(t);
    }

    @Override
    public void serialize(Collection list, JsonGenerator jsonGenerator, SerializerProvider unused) throws IOException {
        jsonGenerator.writeStartArray();

        list.forEach(e -> {
            try {
                if (e != null) {
                    jsonGenerator.writeObject(e);
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        });

        jsonGenerator.writeEndArray();
    }
}

Custom serializer to ignore null values in Array:

class ArrayIgnoreNullSerializer extends StdSerializer<Object[]> {
    public ArrayIgnoreNullSerializer() {
        this(null);
    }

    public ArrayIgnoreNullSerializer(Class<Object[]> t) {
        super(t);
    }

    @Override
    public void serialize(Object[] array, JsonGenerator jsonGenerator, SerializerProvider unused) throws IOException {
        jsonGenerator.writeStartArray();

        for (int i = 0; i < array.length; i++) {
            try {
                if (array[i] != null) {
                    jsonGenerator.writeObject(array[i]);
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

        jsonGenerator.writeEndArray();
    }
}

The main just to test it:

public static void main(String[] args) throws IOException {
    Hospital hospital = new Hospital();

    List<String> patients = Arrays.asList(null, "Bob", "Tom", null, null);
    String[] doctors = new String[]{null, "Dr. Grimmer", "Dr. Who", null};

    hospital.setPatients(patients);
    hospital.setDoctors(doctors);

    ObjectMapper mapper = new ObjectMapper();

    SimpleModule module = new SimpleModule();
    module.addSerializer(Collection.class, new CollectionIgnoreNullSerializer());
    // You could apply the custom serialization just to Lists:
    // module.addSerializer(List.class, new CollectionIgnoreNullSerializer());

    module.addSerializer(String[].class, new ArrayIgnoreNullSerializer());
    // You could cover other type of Arrays like this:
    // module.addSerializer(Integer[].class, new ArrayIgnoreNullSerializer());
    mapper.registerModule(module);

    System.out.println(mapper.writeValueAsString(hospital));
}

And this is the serialized json:

{"patients":["Bob","Tom"],"doctors":["Dr. Grimmer","Dr. Who"]}

Related