spring-data-rest icon indicating copy to clipboard operation
spring-data-rest copied to clipboard

Empty collections are not serialized properly with default media type json [DATAREST-1346]

Open spring-projects-issues opened this issue 6 years ago • 4 comments

MitchelLabonte opened DATAREST-1346 and commented

 

When setting the default media type to application/json, an empty collection will be serialized like this:

"content": [ {

"value": [ ],

"relTargetType": "redacted",

"collectionValue": true,

"rel": null

}]

 

This happens because class AbstractRepositoryRestController, method entitiesToResources maps empty collections to an EmptyCollectionEmbeddedWrapper no matter what media type is used. But, the custom deserializer for EmptyCollectionEmbeddedWrapper is only used when using hal as the mediatype


Affects: 3.1.5 (Lovelace SR5)

spring-projects-issues avatar Feb 22 '19 21:02 spring-projects-issues

Ben Madore commented

People have been running into this on Stack Overflow for a few years, and there has been no response from anyone:

 

https://stackoverflow.com/questions/45590207/spring-data-rest-returns-emptycollectionembeddedwrapper-instead-of-empty-collect

https://stackoverflow.com/questions/40654754/empty-collection-returns-single-object-in-spring-data-rest-instead-of-empty-arra

 

spring-projects-issues avatar Apr 17 '19 14:04 spring-projects-issues

David Lopez commented

I'm puzzled to see that this issue is reported and has not been fixed so far.

IMHO, it is quite blocking as returning an empty list of resources is a quite usual case.

 

I'm not aware of any good workaround; all that I have found either does not work or is extremely tricky (and unportable).

 

Sadly, I'll have to remove Spring Data REST from the project; it was promising, but I don't know how I could handle correctly this situation.

 

I read that Resources class handles this situation, but it seems that the latest versions of Spring HATEOAS remove these classes and remove them by EntityModel/CollectionModel which fails in the de-serialization

spring-projects-issues avatar Oct 02 '20 18:10 spring-projects-issues

David Lopez commented

Finally, I had to adapt the solution provided in the previous links to use the types introduced by the Spring HATEOAS 1.x.

@Component
public class ResourceProcessorEmpty implements RepresentationModelProcessor<CollectionModel<Object>> {
    @Override
    public CollectionModel<Object> process(CollectionModel<Object> resourceToThrowAway) {
        if (resourceToThrowAway.getContent().size() != 1) {
            return resourceToThrowAway;
        }
        if (!resourceToThrowAway.getContent().iterator().next().getClass().getCanonicalName().contains("EmptyCollectionEmbeddedWrapper")) {
            return resourceToThrowAway;
        }

        CollectionModel<Object> newResource = new CollectionModel<>(Collections.emptyList());
        newResource.add(resourceToThrowAway.getLinks());
        return newResource;
    }
}

spring-projects-issues avatar Oct 05 '20 13:10 spring-projects-issues

The above workaround works and ensures Spring Data Rest returns an empty list in the 'content' element instead of a 1 element array.

Returning an array with a single element is very strange when there are no rows in the datasource..

johnny-minty avatar May 10 '21 07:05 johnny-minty