Skip to content

Commit 3f14df6

Browse files
committed
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. Fixes: GH-2987.
1 parent 989af7d commit 3f14df6

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)