To ignore the elements in the container that have only null/empty members (the container's members, members) you can create a custom serializer for Container
. Custom serializers are great because they give you ultimate control of how an object is written, but this can also lead to code that is difficult to maintain. I say this because with Jackson you can accomplish practically anything with a custom de/serializer, but there is usually a cleaner way (through annotations for example) for most problems. For this, the OP requested guidance on writing a custom serializer, and I don't know a simpler way to accomplish the desired behavior.
Create a Module
and Custom Serializer
A Jackson Module
is used to encapsulate a deserializer and serializer for a single object. For this example only a serializer is needed, but if you wanted to add a deserializer for Container
you could just add it alongside the serializer inside of ContainerModule
. The following code defines a serializer for Container
that will only write element1
and element2
if at least one of their members are non-null:
public class ContainerModule extends SimpleModule {
private static final String NAME = "ContainerModule";
public ContainerModule() {
super(NAME);
addSerializer(Container.class, new ContainerSerializer());
}
public static class ContainerSerializer extends JsonSerializer<Container> {
@Override
public void serialize(Container container, JsonGenerator jg, SerializerProvider serializers) throws IOException {
if (container != null) {
// start object and write description
jg.writeStartObject();
jg.writeStringField("description", container.description);
// only write Element1 if one of its members exist
Element1 element1 = container.element1;
if (element1 != null) {
if (!Strings.isNullOrEmpty(element1.f11)
&& !Strings.isNullOrEmpty(element1.f12)) {
jg.writeFieldName("element1");
jg.writeObject(element1);
}
}
// only write Element2 if one of its members exist
Element2 element2 = container.element2;
if (element2 != null) {
if (!Strings.isNullOrEmpty(element2.f21)
&& !Strings.isNullOrEmpty(element2.f22)) {
jg.writeFieldName("element2");
jg.writeObject(element2);
}
}
// close the Container object
jg.writeEndObject();
}
}
}
}
Register the Custom Serializer
The serializer can be registered globally on the ObjectMapper
or on the class using @JsonDeserialize
.
ObjectMapper
Registration
ObjectMapper om = new ObjectMapper()
.registerModule(new ContainerModule());
Class-level Registration
@JsonSerialize(using = ContainerModule.ContainerSerializer.class)
public class Container {
String description;
Element1 element1;
Element2 element2;
}
This should produce the following results:
// Full container
{
"description" : "an awesome description",
"element1" : {
"f11" : "f11 value",
"f12" : "f12 value"
},
"element2" : {
"f21" : "f21 value",
"f22" : "f22 value"
}
}
// Null Element1 properties
{
"description" : "an awesome description",
"element2" : {
"f21" : "f21 value",
"f22" : "f22 value"
}
}
// Null Element2 properties
{
"description" : "an awesome description",
"element1" : {
"f11" : "f11 value",
"f12" : "f12 value"
}
}
// Null Element1 and 2 properties
{
"description" : "an awesome description"
}