Fix deserialising from Pageable.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,6 +57,18 @@ public class PageJacksonModule extends Module {
|
||||
@Override
|
||||
public void setupModule(SetupContext context) {
|
||||
context.setMixInAnnotations(Page.class, PageMixIn.class);
|
||||
context.setMixInAnnotations(Pageable.class, PageableMixIn.class);
|
||||
}
|
||||
|
||||
private static PageRequest buildPageRequest(int number, int size, Sort sort) {
|
||||
PageRequest pageRequest;
|
||||
if (sort != null) {
|
||||
pageRequest = PageRequest.of(number, size, sort);
|
||||
}
|
||||
else {
|
||||
pageRequest = PageRequest.of(number, size);
|
||||
}
|
||||
return pageRequest;
|
||||
}
|
||||
|
||||
@JsonDeserialize(as = SimplePageImpl.class)
|
||||
@@ -65,24 +77,29 @@ public class PageJacksonModule extends Module {
|
||||
|
||||
}
|
||||
|
||||
@JsonDeserialize(as = SimplePageable.class)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
private interface PageableMixIn {
|
||||
|
||||
}
|
||||
|
||||
static class SimplePageImpl<T> implements Page<T> {
|
||||
|
||||
private final Page<T> delegate;
|
||||
|
||||
SimplePageImpl(@JsonProperty("content") List<T> content, @JsonProperty("number") int number,
|
||||
@JsonProperty("size") int size, @JsonProperty("totalElements") @JsonAlias({ "total-elements",
|
||||
"total_elements", "totalelements", "TotalElements" }) long totalElements,
|
||||
SimplePageImpl(@JsonProperty("content") List<T> content, @JsonProperty("pageable") Pageable pageable,
|
||||
@JsonProperty("number") @JsonAlias("pageNumber") int number,
|
||||
@JsonProperty("size") @JsonAlias("pageSize") int size,
|
||||
@JsonProperty("totalElements") @JsonAlias({ "total-elements", "total_elements", "totalelements",
|
||||
"TotalElements", "total" }) long totalElements,
|
||||
@JsonProperty("sort") Sort sort) {
|
||||
if (size > 0) {
|
||||
PageRequest pageRequest;
|
||||
if (sort != null) {
|
||||
pageRequest = PageRequest.of(number, size, sort);
|
||||
}
|
||||
else {
|
||||
pageRequest = PageRequest.of(number, size);
|
||||
}
|
||||
PageRequest pageRequest = buildPageRequest(number, size, sort);
|
||||
delegate = new PageImpl<>(content, pageRequest, totalElements);
|
||||
}
|
||||
else if (pageable != null && pageable.getPageSize() > 0) {
|
||||
delegate = new PageImpl<>(content, pageable, totalElements);
|
||||
}
|
||||
else {
|
||||
delegate = new PageImpl<>(content);
|
||||
}
|
||||
@@ -213,4 +230,60 @@ public class PageJacksonModule extends Module {
|
||||
|
||||
}
|
||||
|
||||
static class SimplePageable implements Pageable {
|
||||
|
||||
private final PageRequest delegate;
|
||||
|
||||
SimplePageable(@JsonProperty("pageNumber") int number, @JsonProperty("pageSize") int size,
|
||||
@JsonProperty("sort") Sort sort) {
|
||||
delegate = buildPageRequest(number, size, sort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPageNumber() {
|
||||
return delegate.getPageNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPageSize() {
|
||||
return delegate.getPageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOffset() {
|
||||
return delegate.getOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sort getSort() {
|
||||
return delegate.getSort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pageable next() {
|
||||
return delegate.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pageable previousOrFirst() {
|
||||
return delegate.previousOrFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pageable first() {
|
||||
return delegate.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pageable withPage(int pageNumber) {
|
||||
return delegate.withPage(pageNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return delegate.hasPrevious();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,10 +34,11 @@ import feign.codec.EncodeException;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
/**
|
||||
* This class provides provides support for serializing and deserializing for Spring
|
||||
* {@link Sort} object.
|
||||
* This class provides support for serializing and deserializing for Spring {@link Sort}
|
||||
* object.
|
||||
*
|
||||
* @author Can Bezmen
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class SortJsonComponent {
|
||||
|
||||
@@ -72,13 +73,11 @@ public class SortJsonComponent {
|
||||
TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
|
||||
if (treeNode.isArray()) {
|
||||
ArrayNode arrayNode = (ArrayNode) treeNode;
|
||||
List<Sort.Order> orders = new ArrayList<>();
|
||||
for (JsonNode jsonNode : arrayNode) {
|
||||
Sort.Order order = new Sort.Order(Sort.Direction.valueOf(jsonNode.get("direction").textValue()),
|
||||
jsonNode.get("property").textValue());
|
||||
orders.add(order);
|
||||
}
|
||||
return Sort.by(orders);
|
||||
return toSort(arrayNode);
|
||||
}
|
||||
else if (treeNode.get("orders") != null && treeNode.get("orders").isArray()) {
|
||||
ArrayNode arrayNode = (ArrayNode) treeNode.get("orders");
|
||||
return toSort(arrayNode);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -88,6 +87,16 @@ public class SortJsonComponent {
|
||||
return Sort.class;
|
||||
}
|
||||
|
||||
private static Sort toSort(ArrayNode arrayNode) {
|
||||
List<Sort.Order> orders = new ArrayList<>();
|
||||
for (JsonNode jsonNode : arrayNode) {
|
||||
Sort.Order order = new Sort.Order(Sort.Direction.valueOf(jsonNode.get("direction").textValue()),
|
||||
jsonNode.get("property").textValue());
|
||||
orders.add(order);
|
||||
}
|
||||
return Sort.by(orders);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
* Copyright 2013-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.openfeign.support;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -29,6 +31,7 @@ import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -40,12 +43,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Pedro Mendes
|
||||
* @author Nikita Konev
|
||||
*/
|
||||
public class PageJacksonModuleTests {
|
||||
class PageJacksonModuleTests {
|
||||
|
||||
private static ObjectMapper objectMapper;
|
||||
|
||||
@BeforeAll
|
||||
public static void initialize() {
|
||||
static void initialize() {
|
||||
objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new PageJacksonModule());
|
||||
objectMapper.registerModule(new SortJacksonModule());
|
||||
@@ -53,7 +56,7 @@ public class PageJacksonModuleTests {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "totalElements", "total-elements", "total_elements", "totalelements", "TotalElements" })
|
||||
public void deserializePage(String totalElements) throws JsonProcessingException {
|
||||
void deserializePage(String totalElements) throws JsonProcessingException {
|
||||
// Given
|
||||
String pageJson = "{\"content\":[\"A name\"], \"number\":1, \"size\":2, \"" + totalElements + "\": 3}";
|
||||
// When
|
||||
@@ -67,8 +70,24 @@ public class PageJacksonModuleTests {
|
||||
assertThat(result.getPageable().getPageNumber()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"./src/test/resources/withPageable.json", "./src/test/resources/withoutPageable.json"})
|
||||
void deserializePageFromFileWithPageable(String filePath) throws IOException {
|
||||
File file = new File(filePath);
|
||||
|
||||
Page<?> result = objectMapper.readValue(file, Page.class);
|
||||
|
||||
assertThat(result.getTotalElements()).isEqualTo(11);
|
||||
assertThat(result.getContent()).hasSize(10);
|
||||
assertThat(result.getPageable().getPageNumber()).isEqualTo(0);
|
||||
assertThat(result.getPageable().getSort().getOrderFor("lastName")
|
||||
.getDirection()).isEqualTo(Sort.Direction.DESC);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void serializeAndDeserializeEmpty() throws JsonProcessingException {
|
||||
void serializeAndDeserializeEmpty() throws JsonProcessingException {
|
||||
// Given
|
||||
PageImpl<Object> objects = new PageImpl<>(new ArrayList<>(), Pageable.ofSize(1), 0);
|
||||
String pageJson = objectMapper.writeValueAsString(objects);
|
||||
@@ -81,7 +100,7 @@ public class PageJacksonModuleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeAndDeserializeFilledMultiple() throws JsonProcessingException {
|
||||
void serializeAndDeserializeFilledMultiple() throws JsonProcessingException {
|
||||
// Given
|
||||
ArrayList<Object> pageElements = new ArrayList<>();
|
||||
pageElements.add("first element");
|
||||
@@ -104,7 +123,7 @@ public class PageJacksonModuleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeAndDeserializeEmptyCascade() throws JsonProcessingException {
|
||||
void serializeAndDeserializeEmptyCascade() throws JsonProcessingException {
|
||||
// Given
|
||||
PageImpl<Object> objects = new PageImpl<>(new ArrayList<>(), Pageable.ofSize(1), 0);
|
||||
String pageJson = objectMapper.writeValueAsString(objects);
|
||||
@@ -123,7 +142,7 @@ public class PageJacksonModuleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeAndDeserializeFilledMultipleCascade() throws JsonProcessingException {
|
||||
void serializeAndDeserializeFilledMultipleCascade() throws JsonProcessingException {
|
||||
// Given
|
||||
ArrayList<Object> pageElements = new ArrayList<>();
|
||||
pageElements.add("first element in cascaded serialization");
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"id": 3,
|
||||
"lastName": "Williams",
|
||||
"firstName": "Thomas",
|
||||
"email": "w.t@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"lastName": "Smith",
|
||||
"firstName": "James",
|
||||
"email": "s.j@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"lastName": "Scott",
|
||||
"firstName": "Steven",
|
||||
"email": "s.s@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"lastName": "Rodriguez",
|
||||
"firstName": "Daniel",
|
||||
"email": "r.d@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"lastName": "Martinez",
|
||||
"firstName": "Robert",
|
||||
"email": "m.r@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"lastName": "Jones",
|
||||
"firstName": "James",
|
||||
"email": "j.j@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"lastName": "Johnson",
|
||||
"firstName": "Robert",
|
||||
"email": "j.r@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"lastName": "Garcia",
|
||||
"firstName": "William",
|
||||
"email": "g.w@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"lastName": "Davis",
|
||||
"firstName": "Richard",
|
||||
"email": "d.r@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"lastName": "Brown",
|
||||
"firstName": "Paul",
|
||||
"email": "b.p@my.domain.com"
|
||||
}
|
||||
],
|
||||
|
||||
"pageable": {
|
||||
"pageNumber": 0,
|
||||
"pageSize": 10,
|
||||
"sort": {
|
||||
"orders": [
|
||||
{
|
||||
"direction": "DESC",
|
||||
"property": "lastName",
|
||||
"ignoreCase": false,
|
||||
"nullHandling": "NATIVE",
|
||||
"ascending": false,
|
||||
"descending": true
|
||||
}
|
||||
],
|
||||
"sorted": true,
|
||||
"empty": false,
|
||||
"unsorted": false
|
||||
},
|
||||
"paged": true,
|
||||
"unpaged": false
|
||||
},
|
||||
"total": 11,
|
||||
"last": false,
|
||||
"first": true,
|
||||
"empty": false
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"id": 3,
|
||||
"lastName": "Williams",
|
||||
"firstName": "Thomas",
|
||||
"email": "w.t@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"lastName": "Smith",
|
||||
"firstName": "James",
|
||||
"email": "s.j@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"lastName": "Scott",
|
||||
"firstName": "Steven",
|
||||
"email": "s.s@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"lastName": "Rodriguez",
|
||||
"firstName": "Daniel",
|
||||
"email": "r.d@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"lastName": "Martinez",
|
||||
"firstName": "Robert",
|
||||
"email": "m.r@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"lastName": "Jones",
|
||||
"firstName": "James",
|
||||
"email": "j.j@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"lastName": "Johnson",
|
||||
"firstName": "Robert",
|
||||
"email": "j.r@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"lastName": "Garcia",
|
||||
"firstName": "William",
|
||||
"email": "g.w@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"lastName": "Davis",
|
||||
"firstName": "Richard",
|
||||
"email": "d.r@my.domain.com"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"lastName": "Brown",
|
||||
"firstName": "Paul",
|
||||
"email": "b.p@my.domain.com"
|
||||
}
|
||||
],
|
||||
"sort": {
|
||||
"orders": [
|
||||
{
|
||||
"direction": "DESC",
|
||||
"property": "lastName",
|
||||
"ignoreCase": false,
|
||||
"nullHandling": "NATIVE",
|
||||
"ascending": false,
|
||||
"descending": true
|
||||
}
|
||||
],
|
||||
"sorted": true,
|
||||
"empty": false,
|
||||
"unsorted": false
|
||||
},
|
||||
"size": 2,
|
||||
"total": 11,
|
||||
"last": false,
|
||||
"first": true,
|
||||
"empty": false
|
||||
}
|
||||
Reference in New Issue
Block a user