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 a7c85a394..af1a91805 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 @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 the original author or authors. + * Copyright 2013-2025 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. @@ -33,6 +33,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.web.PagedModel; /** * This Jackson module provides support to deserialize Spring {@link Page} objects. @@ -41,6 +42,7 @@ * @author Olga Maciaszek-Sharma * @author Pedro Mendes * @author Nikita Konev + * @author Bruce Stewart */ public class PageJacksonModule extends Module { @@ -88,6 +90,7 @@ static class SimplePageImpl implements Page { private final Page delegate; SimplePageImpl(@JsonProperty("content") List content, @JsonProperty("pageable") Pageable pageable, + @JsonProperty("page") PagedModel.PageMetadata pageMetadata, @JsonProperty("number") @JsonAlias("pageNumber") int number, @JsonProperty("size") @JsonAlias("pageSize") int size, @JsonProperty("totalElements") @JsonAlias({ "total-elements", "total_elements", "totalelements", @@ -100,6 +103,11 @@ static class SimplePageImpl implements Page { else if (pageable != null && pageable.getPageSize() > 0) { delegate = new PageImpl<>(content, pageable, totalElements); } + else if (pageMetadata != null && pageMetadata.size() > 0) { + PageRequest pageRequest = buildPageRequest((int) pageMetadata.number(), (int) pageMetadata.size(), + null); + delegate = new PageImpl<>(content, pageRequest, pageMetadata.totalElements()); + } else { delegate = new PageImpl<>(content); } 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 115968824..447e546e2 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 @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 the original author or authors. + * Copyright 2013-2025 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. @@ -42,6 +42,7 @@ * @author Olga Maciaszek-Sharma * @author Pedro Mendes * @author Nikita Konev + * @author Bruce Stewart */ class PageJacksonModuleTests { @@ -85,6 +86,19 @@ void deserializePageFromFileWithPageable(String filePath) throws IOException { .isEqualTo(Sort.Direction.DESC); } + @ParameterizedTest + @ValueSource(strings = { "./src/test/resources/withPage.json" }) + void deserializePageFromFileWithPage(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()).isEqualTo(Sort.unsorted()); + } + @Test void serializeAndDeserializeEmpty() throws JsonProcessingException { // Given diff --git a/spring-cloud-openfeign-core/src/test/resources/withPage.json b/spring-cloud-openfeign-core/src/test/resources/withPage.json new file mode 100644 index 000000000..306fddacd --- /dev/null +++ b/spring-cloud-openfeign-core/src/test/resources/withPage.json @@ -0,0 +1,70 @@ +{ + "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" + } + ], + "page": { + "number": 0, + "size": 2, + "totalElements": 11, + "totalPages": 6 + } +}