I have a Java class with an Optional field. I am serializing the class to JSON using Jackson 2.8.3 (called from Spring web 4.3.3).
I am hoping to get the serializer to skip the field if the Optional is empty, and serialize the contained string if it is present. An example of the result I'm looking for with a list of two objects:
[
{
"id": 1,
"foo": "bar"
},
{
"id": 2,
}
]
Here the foo Optional is empty for the object with id 2.
Instead, what I get is:
[
{
"id": 1,
"foo": {
"present": true
}
},
{
"id": 2,
"foo": {
"present": false
}
}
]
This is the result even if I annotate the "bar" field in the class like
@JsonInclude(JsonInclude.Include.NON_ABSENT)
public Optional<String> getFoo() { ...
Is there any way I can achieve a result like the first list using the Jackson annotations or a custom serializer?
No need to write custom serializer. Annotate your class with @JsonInclude(JsonInclude.Include.NON_ABSENT)
.
You also need to:
com.fasterxml.jackson.datatype:jackson-datatype-jdk8
as your dependencyobjectMapper.registerModule(new Jdk8Module());
You can use objectMapper.registerModule(new Jdk8Module());
but it serializes with null values.
But still you want to remove null values also from JSON, please use the following code:
objectMapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(true));
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Use a JsonSerializer
to your needs.
Something like this (semi-pseudo):
public class MySer extends JsonSerializer<Opional<?>> {
@Override
public void serialize(Optional<?> optString, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException {
//Check Optional here...
generator.writeString(/* DO SOMETHING HERE WHATEVER */);
}
//Then in your model:
public class ClassWhatever {
@JsonSerialize(using = MySer .class)
public Optional<String> getFoo() { ...
}
To avoid annotating every field with @JsonSerialize you may register your custom serializer to object mapper using
ObjectMapper mapper = new ObjectMapper();
SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null));
testModule.addSerializer(new MyCustomSerializer()); // assuming serializer declares correct class to bind to
mapper.registerModule(testModule);
Also, given solution works only for serialization. Deserialization will fail unless you write your own deserializer. Then you need to annotate every field with @JsonDeserializ
e or register your custom deserializer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With