I want to write a custom serializer that, when it encounters a null value for a set, serializes it as an empty set. I want to pair that with a deserializer which deserializes an empty set back to null. If the collection has elements, it can be serialized/deserialized as normal.
I’ve written a couple of deserializers and they work well but the methods I used there don’t seem applicable to collections. For example, I wrote this to turn empty strings into nulls:
JsonNode node = p.readValueAsTree();
String text = (Objects.isNull(node) ? null : node.asText());
if (StringUtils.isEmpty(text)) {
return null;
}
I don’t think this will work because JsonNode doesn’t have an asSet() method.
I’ve found examples online that look promising but it seems like all the examples of working with collections involve working with the elements inside the collection, not the collection itself.
So far, I’ve been hand-coding this process but I’m sure there’s a better way to deal with it.
I’m at the point of figuring it out by trial and error so any examples, ideas, or advice would be appreciated.
Here’s what I’m thinking it should look like:
@JsonComponent
public class SetDeserializer extends Std???Deserializer<Set<?>> {
public SetDeserializer() {
super(Set.class);
}
@Override
public Set<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = p.readValueAsTree();
Set<?> mySet = (Objects.isNull(node) ? null : node.asSet());
if (CollectionUtils.isEmpty(mySet)) {
return null;
}
return super().deserialize(p, ctxt);
}
}
2
Answers
This is quite simple using ObjectMapper.
This returns a
List
of the Nodes elements by first verifying that the node is an array and is not empty. But, if the list is an empty array node, we return an empty list, and if it isn’t an arrayNode, then we return null.Based on your requirements, I wasn’t sure if the contents of your array list were empty (ie null) or the json node itself is expected to be null. If the JsonNode itself is expected to be null, then you can easily modify this to return an empty list when it is null:
You can test this via the following
Here’s how to use the above code, to deserialize an object into an array of animals
You can reverse this to get your JsonNode.
Edit: Added a working deserializer example
To make it work as it is required:
null
Set
as an emptyJSON Array
[]
JSON Array
[]
asnull
We need to use at the same time:
com.fasterxml.jackson.databind.JsonSerializer
to generate an emptyJSON Array
[]
com.fasterxml.jackson.databind.util.StdConverter
to convert an emptySet
orList
tonull
com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
to register serialiser and converters for all properties.Below example shows all above components and how to use them:
Above code prints:
You can also register converters and null serialiser using annotations directly on the field you want:
In this case you do not need to register
EmptyAsNullCollectionJacksonAnnotationIntrospector
.See also: