Home > Blockchain >  Missing fields are getting deserializing as null instead of an empty object after upgrading Jackson-
Missing fields are getting deserializing as null instead of an empty object after upgrading Jackson-

Time:10-02

I am facing one issue after upgrading Jackson library to 2x version, when fields are missing from input during deserialization, they are getting deserialised to null instead of empty.

Example -

POJO

@Value
@Builder(builderClassName = "ClassABuilder")
@AllArgsConstructor
public class ClassA {
  private String value1;
  private Map<String, String> value2;

  private ClassA() {
    value1 = "someString";
    value2 = ImmutableList.of();
  }
}

Deserialization -

private final IonObjectMapper ionValueMapper;
ionValueMapper.readValue(value, ClassA.class);

ObjectMapper -

IonObjectMapper joiObjectMapper = (IonObjectMapper) new IonObjectMapper()
                .setSerializationInclusion(JsonInclude.Include.ALWAYS)
                .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                .enable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS)
                .enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.PROPERTY)
                .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
                .enable(MapperFeature.AUTO_DETECT_SETTERS)
                .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
                .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
                .setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
                .setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE)
                .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

Input -

{"value1" = "someString"}

Desired Output -

{"value1" = "someString", "value2" = {}}

Current Output -

{"value1" = "someString", "value2" = null}

Is there a way we can configure in the ObjectMapper that missing fields should not be converted to null but empty? I cannot change ClassA.

Jackson packages versions that I am using -

Jackson-core = 2.10.x;
Jackson-databind = 2.10.x;
Jackson-dataformat-xml = 2.10.x;
Jackson-module-jaxb-annotations = 2.10.x;
Jackson-dataformat-ion = 2.10.x;
Jackson-annotations = 2.10.x;

I tried the suggestion in this question but does not work for my case - link

CodePudding user response:

It seems that @JsonSetter(nulls = Nulls.AS_EMPTY) only works "when input contains explicit null value (...) is not usually used in case property value is missing" (reference documentation) which is not your case.

Your best option would be to modify the setter for that map attribute as follows:

@Value
@Builder(builderClassName = "ClassABuilder")
@AllArgsConstructor
public class ClassA {
    private String value1;
    private Map<String, String> value2;

    private ClassA() {
      value1 = "someString";
      value2 = ImmutableList.of();
    }

    public void setValue2(Map<String, String> value2) {
        if (value2 != null) {
            this.value2 = homes;
        } else {
            this.value2 = ImmutableList.of()
        }
    }
}

CodePudding user response:

As João Dias already said, the @JsonSetter(nulls = Nulls.AS_EMPTY) annotation is meant for explicit null values.

If you can't change ClassA, you could make a subclass with a default constructor that sets your value2 to an empty map (assuming ClassA has a setter for value2).

class ClassAExtended extends ClassA {
    public ClassAExtended() {
        setValue2(new HashMap<>());     
    }
}

The variable you read to can still be of type ClassA:

private final IonObjectMapper ionValueMapper;
ClassA classA = ionValueMapper.readValue(value, ClassAExtended.class);
  • Related