Allow deserializing ListResult (#7711)

#### What type of PR is this?

/kind improvement
/area core
/milestone 2.21.x

#### What this PR does / why we need it:

This PR allows ListResult to be deserialized with JSON. So we can resolve ListResult response of APIs correctly.

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/7725/head
John Niang 2025-08-21 18:15:48 +08:00 committed by GitHub
parent 4ac80f5eb3
commit 956e23dd7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 73 additions and 1 deletions

View File

@ -2,6 +2,7 @@ package run.halo.app.extension;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import java.util.ArrayList; import java.util.ArrayList;
@ -32,7 +33,12 @@ public class ListResult<T> implements Iterable<T>, Supplier<Stream<T>> {
@Schema(description = "A chunk of items.", requiredMode = REQUIRED) @Schema(description = "A chunk of items.", requiredMode = REQUIRED)
private final List<T> items; private final List<T> items;
public ListResult(int page, int size, long total, List<T> items) { @JsonCreator
public ListResult(
@JsonProperty("page") int page,
@JsonProperty("size") int size,
@JsonProperty("total") long total,
@JsonProperty("items") List<T> items) {
Assert.isTrue(total >= 0, "Total elements must be greater than or equal to 0"); Assert.isTrue(total >= 0, "Total elements must be greater than or equal to 0");
if (page < 0) { if (page < 0) {
page = 0; page = 0;

View File

@ -1,13 +1,19 @@
package run.halo.app.extension; package run.halo.app.extension;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
class ListResultTest { class ListResultTest {
@ -63,6 +69,66 @@ class ListResultTest {
assertEquals(Optional.of("A"), ListResult.first(listResult)); assertEquals(Optional.of("A"), ListResult.first(listResult));
} }
@Test
void serializationTest() throws JsonProcessingException {
var result = new ListResult<>(1, 10, 100, List.of("a", "b", "c"));
var json = JsonMapper.builder()
.build()
.writeValueAsString(result);
JSONAssert.assertEquals("""
{
"page": 1,
"size": 10,
"total": 100,
"items": [
"a",
"b",
"c"
],
"first": true,
"last": false,
"hasNext": true,
"hasPrevious": false,
"totalPages": 10
}
""", json, true);
}
@Test
void deserializationTest() throws JsonProcessingException {
var json = """
{
"page": 2,
"size": 10,
"total": 100,
"items": [
"a",
"b",
"c"
],
"first": false,
"last": false,
"hasNext": true,
"hasPrevious": true,
"totalPages": 10
}
""";
var result = JsonMapper.builder()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.build()
.readValue(json, new TypeReference<ListResult<String>>() {
});
assertEquals(2, result.getPage());
assertEquals(100, result.getTotal());
assertEquals(10, result.getTotalPages());
assertEquals(10, result.getSize());
assertFalse(result.isFirst());
assertFalse(result.isLast());
assertTrue(result.hasNext());
assertTrue(result.hasPrevious());
assertEquals(List.of("a", "b", "c"), result.getItems());
}
private void assertSubList(List<Integer> list) { private void assertSubList(List<Integer> list) {
var result = ListResult.subList(list, 0, 0); var result = ListResult.subList(list, 0, 0);
assertEquals(list, result); assertEquals(list, result);