-
Notifications
You must be signed in to change notification settings - Fork 474
Description
I am using Spring HATEOAS 0.25.0.RELEASE along with Spring Data REST 3.0.11.RELEASE (via Spring Boot 2.0.6.RELEASE), and a component from Spring Data REST does not honor the Jackson settings for empty collections when the type contained in the collection is not a primitive or default type.
I have a domain class annotated with @JsonInclude(JsonInclude.Include.NON_EMPTY)
. Let's say this class is called ExampleObject
and it has two fields: label
, a String, and nestedObjects
, a Collection of ExampleObjects
.
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class ExampleObject {
private String label;
private Collection<ExampleObject> nestedObjects;
public ExampleObject() {
nestedObjects = new ArrayList<ExampleObject>();
}
// Getters and setters
}
A default Jackson ObjectMapper
will omit fields for which the value is an empty collection or array in the JSON output when an ExampleObject
is serialized (e.g., if I Accept
application/json
from one of my REST endpoints). See the below mock example, assuming I am retrieving an ExampleObject
with an empty nestedObjects
Collection.
{
"label" : "Example Object"
}
However, the combination of Spring HATEOAS and Spring Data REST does not seem to honor either of the above Jackson configuration methods. If I Accept
application/hal+json
, empty arrays and collections are always serialized as "[ ]". See the below mock example, which uses the same ExampleObject
as above (wrapped in a Resource
).
{
"label" : "Example Object",
"nestedObjects" : [ ],
"_links" : {
"ex:example" : {
"href" : "http://localhost:8080/example"
},
"self" : {
"href" : "http://localhost:8080"
},
"curies" : [ {
"href" : "http://example.com/{rel}",
"name" : "ex",
"templated" : true
} ]
}
}
I'd expect to see something more like this (note the omitted "nestedObjects" field):
{
"label" : "Example Object",
"_links" : {
"ex:example" : {
"href" : "http://localhost:8080/example"
},
"self" : {
"href" : "http://localhost:8080"
},
"curies" : [ {
"href" : "http://example.com/{rel}",
"name" : "ex",
"templated" : true
} ]
}
}
I believe this behavior is possibly related to NestedEntitySerializer
, which is defined in PersistentEntityJackson2Module.
NestedEntitySerializer
extends com.fasterxml.jackson.databind.JsonSerializer
, which has a method called isEmpty(SerializerProvider provider, T value)
. The default implementation simply checks if value
is null
.
NestedEntitySerializer#isEmpty(SerializerProvider provider, T value)
is being called by com.fasterxml.jackson.databind.ser.BeanPropertyWriter#serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov)
when serializing a Resource
.
A potential way to properly honor the @JsonInclude(NON_EMPTY)
annotation and the WRITE_EMPTY_JSON_ARRAYS
serialization feature is for NestedEntitySerializer
to override the default implementation of isEmpty(SerializerProvider provider, T value)
and check for empty collections, arrays, maps, and strings in addition to null values.
However, the real problem may be that NestedEntitySerializer
is being used in the first place and another Serializer should be used instead in this case.