From ea3fb866905cc70377f470f49e4df1a2afa0c48a Mon Sep 17 00:00:00 2001 From: Can Bezmen Date: Tue, 28 Apr 2020 12:40:04 +0300 Subject: [PATCH] Sort Support for feign pagination --- .../openfeign/support/PageJacksonModule.java | 15 +++- .../openfeign/support/SortJsonComponent.java | 88 +++++++++++++++++++ .../support/PageJacksonModuleTests.java | 18 +++- 3 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJsonComponent.java diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PageJacksonModule.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PageJacksonModule.java index c21aa177..255e3872 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PageJacksonModule.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PageJacksonModule.java @@ -64,10 +64,17 @@ public class PageJacksonModule extends Module { private final Page delegate; SimplePageImpl(@JsonProperty("content") List content, - @JsonProperty("number") int number, @JsonProperty("size") int size, - @JsonProperty("totalElements") long totalElements) { - delegate = new PageImpl<>(content, PageRequest.of(number, size), - totalElements); + @JsonProperty("number") int number, @JsonProperty("size") int size, + @JsonProperty("totalElements") long totalElements, @JsonProperty("sort") Sort sort) { + PageRequest pageRequest; + if (sort != null) { + pageRequest = PageRequest.of(number, size, sort); + } + else { + pageRequest = PageRequest.of(number, size); + } + delegate = new PageImpl<>(content, pageRequest, totalElements); + } @JsonProperty diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJsonComponent.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJsonComponent.java new file mode 100644 index 00000000..64bc6813 --- /dev/null +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJsonComponent.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2020 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.openfeign.support; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.node.ArrayNode; + +import org.springframework.data.domain.Sort; + +/** + * This class provides support to serialize and deserialize spring {@link Sort} object. + * @author canbezmen + */ +public class SortJsonComponent { + + public static class SortSerializer extends JsonSerializer { + + @Override + public void serialize(Sort value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + value.iterator().forEachRemaining(v -> { + try { + gen.writeObject(v); + } + catch (IOException e) { + e.printStackTrace(); + } + }); + gen.writeEndArray(); + } + + @Override + public Class handledType() { + return Sort.class; + } + + } + + public static class SortDeserializer extends JsonDeserializer { + + @Override + public Sort deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser); + if (treeNode.isArray()) { + ArrayNode arrayNode = (ArrayNode) treeNode; + List 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 null; + } + + @Override + public Class handledType() { + return Sort.class; + } + + } +} diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java index 465617fd..6e954a23 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java @@ -16,12 +16,16 @@ package org.springframework.cloud.openfeign.support; +import java.util.Optional; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; +import org.springframework.data.domain.Sort; import static org.assertj.core.api.Assertions.assertThat; @@ -35,13 +39,16 @@ public class PageJacksonModuleTests { @BeforeAll public static void initialize() { objectMapper = new ObjectMapper(); - objectMapper.registerModule(new PageJacksonModule()); + SimpleModule module = new SimpleModule(); + module.addSerializer(Sort.class, new SortJsonComponent.SortSerializer()); + module.addDeserializer(Sort.class, new SortJsonComponent.SortDeserializer()); + objectMapper.registerModules(new PageJacksonModule(), module); } @Test public void deserializePage() throws JsonProcessingException { // Given - String pageJson = "{\"content\":[\"A name\"], \"number\":1, \"size\":2, \"totalElements\": 3}"; + String pageJson = "{\"content\":[\"A name\"],\"number\":1,\"size\":2,\"totalElements\":3,\"sort\":[{\"direction\":\"ASC\",\"property\":\"field\",\"ignoreCase\":false,\"nullHandling\":\"NATIVE\",\"descending\":false,\"ascending\":true}]}"; // When Page result = objectMapper.readValue(pageJson, Page.class); // Then @@ -51,6 +58,13 @@ public class PageJacksonModuleTests { assertThat(result.getPageable()).isNotNull(); assertThat(result.getPageable().getPageSize()).isEqualTo(2); assertThat(result.getPageable().getPageNumber()).isEqualTo(1); + assertThat(result.getPageable().getSort()).hasSize(1); + Optional optionalOrder = result.getPageable().getSort().get().findFirst(); + if (optionalOrder.isPresent()) { + Sort.Order order = optionalOrder.get(); + assertThat(order.getDirection()).isEqualTo(Sort.Direction.ASC); + assertThat(order.getProperty()).isEqualTo("field"); + } } }