Assuming I have a POJO like this:
public static class Test {
private Optional<String> something;
}
And a Jackson mapper like this:
var OBJECT_MAPPER = JsonMapper.builder()
.addModule(new Jdk8Module())
.serializationInclusion(JsonInclude.Include.NON_ABSENT)
.build();
If I deserialize the JSON string {"something": null}
, I get a Test
object with something=null
. Instead of that, I want to get a Test object with something=Optional.EMPTY
.
My desired deserialization strategy for Optional is:
- null → not provided
- Optional.empty() → provided null
- Optional.of() → provided not null
The above can be achieved if I keep the default serializationInclusion
(remove the serializationInclusion(JsonInclude.Include.NON_ABSENT)
setting). This results in serializing everything and including nulls in the JSON string output, which is not what I want.
Test test = new Test();
// This should serialize to {}, not {"something": null}
Test test2 = new Test();
test2.setSomething(Optional.EMPTY);
// This should also serialize to {}, not {"something": null}
TLTR: is there a way to separate the serializationInclusion
separately for serialization and deserialization?
2
Answers
I figured out what I was doing wrong, and it was very simple, I just got stuck: I wasn't using
readValue
for Deserialization, but insteadconvertValue
.As the javadoc of
convertValue
mentions:So since the
serializationInclusion
was set to skip nulls on output, the field was being removed completely in the intermediate step.Reproduction example:
If you run the above test, it prints the following:
In the last test with
convertValue
we can see that instead of deserializing the value toOptional.empty
, we got null, which is expected according to whatconvertValue
does.You can do this with a custom serializer: