Skip to content

Spring Data Page doesn't serialize Sort to JSON correctly [DATACMNS-1244] #1683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spring-projects-issues opened this issue Jan 17, 2018 · 7 comments
Assignees
Labels
has: design-decision An issue that contains a design decision about its topic status: declined A suggestion or change that we don't feel we should currently apply

Comments

@spring-projects-issues
Copy link

Oleg Danyliuk opened DATACMNS-1244 and commented

This issue appeared in Spring-Data release 2. In latest version 1.13.9 (and older) it works fine.

Controller code:

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }

    @RequestMapping(value = "sorttest", method = RequestMethod.GET)
    public Page<Integer> getDummy() {
        return new PageImpl<>(Collections.singletonList(1), new PageRequest(0, 5, new Sort("asdf")), 1);
    }

}

Same for Spring-Data 2 style:

Pageable pageable = PageRequest.of(0, 10, new Sort(Sort.Direction.ASC, "asd"));
PageImpl<Integer> page = new PageImpl<Integer>(Lists.newArrayList(1,2,3), pageable, 3);
return page;

Configuration:

@SpringBootApplication
@EnableWebMvc
@EnableSpringDataWebSupport
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Also tried simple Spring application without Spring Boot with Java config as well as with XML config. Result is same:

{
    "content": [
        1
    ],
    "pageable": {
        "sort": {
            "sorted": true,
            "unsorted": false
        },
        "offset": 0,
        "pageSize": 5,
        "pageNumber": 0,
        "paged": true,
        "unpaged": false
    },
    "totalElements": 1,
    "last": true,
    "totalPages": 1,
    "size": 5,
    "number": 0,
    "sort": {
        "sorted": true,
        "unsorted": false
    },
    "numberOfElements": 1,
    "first": true
}

If I change Spring-Data version to 1.X I'm getting correct JSON response for sorting object:

{
    "content": [
        1
    ],
    "totalElements": 1,
    "totalPages": 1,
    "last": true,
    "size": 5,
    "number": 0,
    "sort": [
        {
            "direction": "ASC",
            "property": "asdf",
            "ignoreCase": false,
            "nullHandling": "NATIVE",
            "ascending": true,
            "descending": false
        }
    ],
    "numberOfElements": 1,
    "first": true
}

It seems I tried everything, I didn't find any notification on sort changes in changelog, I didn't find such issue in Spring JIRA.

So the question is how do I get with spring-data 2.X libs JSON with sorting like:

"sort": [
    {
        "direction": "ASC",
        "property": "asdf",
        "ignoreCase": false,
        "nullHandling": "NATIVE",
        "ascending": true,
        "descending": false
    }
]

instead of:

"sort": {
    "sorted": true,
    "unsorted": false
}

Affects: 2.0.1 (Kay SR1), 2.0.2 (Kay SR2)

Reference URL: https://stackoverflow.com/questions/48263935/spring-data-page-doesnt-serialize-sort-to-json-correctly

Issue Links:

  • DATACMNS-1825 I think PageImpl may be need a no args constructor
    ("is duplicated by")

1 votes, 5 watchers

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

Sort is a domain type and we absolutely don't guarantee any default JSON representation (I'd be interested to hear where this assumption comes from). If you need to serialize Sort instance into a dedicated format, you need to provide a custom serializer yourself.

@spring-projects-issues
Copy link
Author

Oleg Danyliuk commented

this format
"sort": [
{
"direction": "ASC",
"property": "asdf",
"ignoreCase": false,
"nullHandling": "NATIVE",
"ascending": true,
"descending": false
}
]
worked for spring-date 1.X, so I expected that would be same for version 2 and I couldn't find any changes related to that, so seemed as a bug to me.
This JSON representation is simple and straightworward, its just plain serialization of fields in Sort class. So not clear where default serializer took those sorted and unsorted fields

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

But why? This is a domain class. Just because you hand it to Jackson at it creates some representation from it, it doesn't mean we guarantee it. Never rely on the default representation generated from a class you don't control

@spring-projects-issues
Copy link
Author

antonio-marrero commented

It is a pity that in the Spring framework you need to tweak the JSON parser or create a DTO wrapper just to have a REST pagination with sorting.

I think a default useful representation should be provided following the old Spring motto "convention over configuration"

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

It's not about mottos, it's about separation of concerns

@spring-projects-issues
Copy link
Author

antonio-marrero commented

Good point (y)

@spring-projects-issues
Copy link
Author

Ruslan Stelmachenko commented

Oliver Drotbohm

I'd be interested to hear where this assumption comes from

 

I think the assumption comes from the fact that Page class was promoted by many guides as the class that controller can safely return. And many guides just return a default implementation of this class from controller, as returned by repository layer from spring-data. Page class even has a convenience method "map" for this use case to.

spring-cloud-openfeign-core project also has a PageJacksonModule class, that "provides support to deserialize spring {@link Page} objects.". And the implementation of this class as I see just uses these fields:

  • content
  • page
  • size
  • totalElements

to deserialize a JSON into it's inner SimplePageImpl implementation.

Obviously this will not work as intended when other side uses new spring-data because new PageImpl doesn't contain the "page" property.

So, I understand that it's wrong to serialize a PageImpl and expect a stable JSON representation. But as you see even a "standard" project from Spring ecosystem (spring-cloud-openfeign-core) wrongly assumes this representation is stable.

So, maybe this is not spring-data's responsibility, but if spring-boot (for example) can provide a default JSON representation for PageImpl in it's starter, it will be good thing, as many forget to think about this and wrongly "rely on the default representation generated from a class you don't control"

@spring-projects-issues spring-projects-issues added type: bug A general bug status: declined A suggestion or change that we don't feel we should currently apply in: core Issues in core support labels Dec 30, 2020
@mp911de mp911de added has: design-decision An issue that contains a design decision about its topic and removed type: bug A general bug in: core Issues in core support labels Nov 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has: design-decision An issue that contains a design decision about its topic status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

3 participants