Skip to content

Commit 69b149e

Browse files
committed
GH-2987 - Fix broken serialization of Unpaged instances.
We now reinstantiate the serialization of Unpaged instances as plain INSTANCE strings as they were rendered before Unpaged was changed from an enum into a class. Note, that we still strongly advise, not to serialize Page instances directly as it's a domain type, its Jackson-level surface is subject to change if we need to change the type's API for unrelated reasons.
1 parent 989af7d commit 69b149e

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

Diff for: src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java

+52
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,19 @@
1515
*/
1616
package org.springframework.data.web.config;
1717

18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
1820
import org.springframework.context.annotation.Bean;
21+
import org.springframework.data.domain.Page;
22+
import org.springframework.data.domain.PageImpl;
1923
import org.springframework.data.geo.GeoModule;
24+
import org.springframework.lang.Nullable;
25+
import org.springframework.util.ClassUtils;
26+
27+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
28+
import com.fasterxml.jackson.databind.module.SimpleModule;
29+
import com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase;
30+
import com.fasterxml.jackson.databind.util.StdConverter;
2031

2132
/**
2233
* JavaConfig class to export Jackson specific configuration.
@@ -29,4 +40,45 @@ public class SpringDataJacksonConfiguration implements SpringDataJacksonModules
2940
public GeoModule jacksonGeoModule() {
3041
return new GeoModule();
3142
}
43+
44+
@Bean
45+
public PageModule pageModule() {
46+
return new PageModule();
47+
}
48+
49+
public static class PageModule extends SimpleModule {
50+
51+
private static final long serialVersionUID = 275254460581626332L;
52+
53+
private static final String UNPAGED_TYPE_NAME = "org.springframework.data.domain.Unpaged";
54+
private static final Class<?> UNPAGED_TYPE;
55+
56+
static {
57+
UNPAGED_TYPE = ClassUtils.resolveClassName(UNPAGED_TYPE_NAME, PageModule.class.getClassLoader());
58+
}
59+
60+
public PageModule() {
61+
addSerializer(UNPAGED_TYPE, new UnpagedAsInstanceSerializer());
62+
}
63+
64+
/**
65+
* A Jackson serializer rendering instances of {@link org.springframework.data.domain.Unpaged} as {@code INSTANCE}
66+
* as it was previous rendered.
67+
*
68+
* @author Oliver Drotbohm
69+
*/
70+
static class UnpagedAsInstanceSerializer extends ToStringSerializerBase {
71+
72+
private static final long serialVersionUID = -1213451755610144637L;
73+
74+
public UnpagedAsInstanceSerializer() {
75+
super(Object.class);
76+
}
77+
78+
@Override
79+
public String valueToString(@Nullable Object value) {
80+
return "INSTANCE";
81+
}
82+
}
83+
}
3284
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.web;
17+
18+
import static org.assertj.core.api.Assertions.*;
19+
20+
import java.util.Collections;
21+
22+
import org.junit.jupiter.api.Test;
23+
import org.springframework.data.domain.PageImpl;
24+
import org.springframework.data.web.config.SpringDataJacksonConfiguration;
25+
26+
import com.fasterxml.jackson.databind.ObjectMapper;
27+
28+
/**
29+
* Unit tests for PageImpl serialization.
30+
*
31+
* @author Oliver Drotbohm
32+
*/
33+
class PageImplJsonSerializationUnitTests {
34+
35+
@Test
36+
void serializesPageImplAsJson() {
37+
38+
ObjectMapper mapper = new ObjectMapper();
39+
mapper.registerModule(new SpringDataJacksonConfiguration.PageModule());
40+
41+
assertThatNoException().isThrownBy(() -> {
42+
mapper.writeValueAsString(new PageImpl<>(Collections.emptyList()));
43+
});
44+
}
45+
}

0 commit comments

Comments
 (0)