Browse Source

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.
pull/3028/head
Oliver Drotbohm 2 years ago
parent
commit
3f14df6562
No known key found for this signature in database
GPG Key ID: 9EB72C54FB72F2A7
  1. 52
      src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java
  2. 45
      src/test/java/org/springframework/data/web/PageImplJsonSerializationUnitTests.java

52
src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java

@ -15,8 +15,19 @@ @@ -15,8 +15,19 @@
*/
package org.springframework.data.web.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.geo.GeoModule;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase;
import com.fasterxml.jackson.databind.util.StdConverter;
/**
* JavaConfig class to export Jackson specific configuration.
@ -29,4 +40,45 @@ public class SpringDataJacksonConfiguration implements SpringDataJacksonModules @@ -29,4 +40,45 @@ public class SpringDataJacksonConfiguration implements SpringDataJacksonModules
public GeoModule jacksonGeoModule() {
return new GeoModule();
}
@Bean
public PageModule pageModule() {
return new PageModule();
}
public static class PageModule extends SimpleModule {
private static final long serialVersionUID = 275254460581626332L;
private static final String UNPAGED_TYPE_NAME = "org.springframework.data.domain.Unpaged";
private static final Class<?> UNPAGED_TYPE;
static {
UNPAGED_TYPE = ClassUtils.resolveClassName(UNPAGED_TYPE_NAME, PageModule.class.getClassLoader());
}
public PageModule() {
addSerializer(UNPAGED_TYPE, new UnpagedAsInstanceSerializer());
}
/**
* A Jackson serializer rendering instances of {@link org.springframework.data.domain.Unpaged} as {@code INSTANCE}
* as it was previous rendered.
*
* @author Oliver Drotbohm
*/
static class UnpagedAsInstanceSerializer extends ToStringSerializerBase {
private static final long serialVersionUID = -1213451755610144637L;
public UnpagedAsInstanceSerializer() {
super(Object.class);
}
@Override
public String valueToString(@Nullable Object value) {
return "INSTANCE";
}
}
}
}

45
src/test/java/org/springframework/data/web/PageImplJsonSerializationUnitTests.java

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
/*
* Copyright 2024 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.data.web;
import static org.assertj.core.api.Assertions.*;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.web.config.SpringDataJacksonConfiguration;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Unit tests for PageImpl serialization.
*
* @author Oliver Drotbohm
*/
class PageImplJsonSerializationUnitTests {
@Test
void serializesPageImplAsJson() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SpringDataJacksonConfiguration.PageModule());
assertThatNoException().isThrownBy(() -> {
mapper.writeValueAsString(new PageImpl<>(Collections.emptyList()));
});
}
}
Loading…
Cancel
Save