Skip to content

Commit 93c25b0

Browse files
christophstroblmp911de
authored andcommitted
Switch Jackson default mapping default from NON_FINAL to EVERYTHING.
Closes #1566 Original pull request: #2237.
1 parent e53a576 commit 93c25b0

File tree

4 files changed

+73
-6
lines changed

4 files changed

+73
-6
lines changed

src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java

+29-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.redis.hash;
1717

18+
import static com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping.*;
19+
1820
import java.io.IOException;
1921
import java.text.ParseException;
2022
import java.util.ArrayList;
@@ -39,8 +41,10 @@
3941
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
4042
import com.fasterxml.jackson.core.JsonGenerator;
4143
import com.fasterxml.jackson.core.JsonParser;
44+
import com.fasterxml.jackson.core.TreeNode;
4245
import com.fasterxml.jackson.databind.DeserializationContext;
4346
import com.fasterxml.jackson.databind.DeserializationFeature;
47+
import com.fasterxml.jackson.databind.JavaType;
4448
import com.fasterxml.jackson.databind.JsonDeserializer;
4549
import com.fasterxml.jackson.databind.JsonNode;
4650
import com.fasterxml.jackson.databind.JsonSerializer;
@@ -49,7 +53,9 @@
4953
import com.fasterxml.jackson.databind.SerializationFeature;
5054
import com.fasterxml.jackson.databind.SerializerProvider;
5155
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
56+
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
5257
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
58+
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
5359
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
5460
import com.fasterxml.jackson.databind.module.SimpleModule;
5561
import com.fasterxml.jackson.databind.ser.std.CalendarSerializer;
@@ -157,9 +163,30 @@ public class Jackson2HashMapper implements HashMapper<Object, String, Object> {
157163
*/
158164
public Jackson2HashMapper(boolean flatten) {
159165

160-
this(new ObjectMapper().findAndRegisterModules(), flatten);
166+
this(new ObjectMapper() {
167+
168+
@Override
169+
protected TypeResolverBuilder<?> _constructDefaultTypeResolverBuilder(DefaultTyping applicability,
170+
PolymorphicTypeValidator ptv) {
171+
return new DefaultTypeResolverBuilder(applicability, ptv) {
172+
public boolean useForType(JavaType t) {
173+
174+
if (t.isPrimitive()) {
175+
return false;
176+
}
177+
178+
if (EVERYTHING.equals(_appliesFor)) {
179+
return !TreeNode.class.isAssignableFrom(t.getRawClass());
180+
}
181+
182+
return super.useForType(t);
183+
}
184+
};
185+
}
186+
}.findAndRegisterModules(), flatten);
161187

162-
typingMapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
188+
typingMapper.activateDefaultTyping(typingMapper.getPolymorphicTypeValidator(), DefaultTyping.EVERYTHING,
189+
As.PROPERTY);
163190
typingMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
164191

165192
// Prevent splitting time types into arrays. E

src/main/java/org/springframework/data/redis/serializer/GenericJackson2JsonRedisSerializer.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
3131
import com.fasterxml.jackson.databind.SerializerProvider;
3232
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
33+
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
3334
import com.fasterxml.jackson.databind.module.SimpleModule;
3435
import com.fasterxml.jackson.databind.ser.SerializerFactory;
3536
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
@@ -71,10 +72,10 @@ public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName
7172
registerNullValueSerializer(mapper, classPropertyTypeName);
7273

7374
if (StringUtils.hasText(classPropertyTypeName)) {
74-
mapper.activateDefaultTypingAsProperty(mapper.getPolymorphicTypeValidator(), DefaultTyping.NON_FINAL,
75+
mapper.activateDefaultTypingAsProperty(mapper.getPolymorphicTypeValidator(), DefaultTyping.EVERYTHING,
7576
classPropertyTypeName);
7677
} else {
77-
mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), DefaultTyping.NON_FINAL, As.PROPERTY);
78+
mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), DefaultTyping.EVERYTHING, As.PROPERTY);
7879
}
7980
}
8081

@@ -190,5 +191,11 @@ public void serialize(NullValue value, JsonGenerator jgen, SerializerProvider pr
190191
jgen.writeStringField(classIdentifier, NullValue.class.getName());
191192
jgen.writeEndObject();
192193
}
194+
195+
@Override
196+
public void serializeWithType(NullValue value, JsonGenerator gen, SerializerProvider serializers,
197+
TypeSerializer typeSer) throws IOException {
198+
serialize(value, gen, serializers);
199+
}
193200
}
194201
}

src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java

+14
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,15 @@ void dateValueShouldBeTreatedCorrectly() {
183183
assertBackAndForwardMapping(source);
184184
}
185185

186+
@Test // GH-1566
187+
void mapFinalClass() {
188+
189+
MeFinal source = new MeFinal();
190+
source.value = "id-1";
191+
192+
assertBackAndForwardMapping(source);
193+
}
194+
186195
@Data
187196
public static class WithList {
188197
List<String> strings;
@@ -206,4 +215,9 @@ private static class WithDates {
206215
private LocalDate localDate;
207216
private LocalDateTime localDateTime;
208217
}
218+
219+
@Data
220+
public static final class MeFinal {
221+
private String value;
222+
}
209223
}

src/test/java/org/springframework/data/redis/serializer/GenericJackson2JsonRedisSerializerUnitTests.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
import static org.springframework.test.util.ReflectionTestUtils.*;
2121
import static org.springframework.util.ObjectUtils.*;
2222

23+
import lombok.Data;
24+
2325
import java.io.IOException;
2426

2527
import org.junit.jupiter.api.Test;
2628
import org.mockito.Mockito;
27-
2829
import org.springframework.beans.BeanUtils;
2930
import org.springframework.cache.support.NullValue;
3031

@@ -141,14 +142,26 @@ void shouldSerializeNullValueSoThatItCanBeDeserializedWithDefaultTypingEnabled()
141142
void shouldSerializeNullValueWithCustomObjectMapper() {
142143

143144
ObjectMapper mapper = new ObjectMapper();
144-
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
145+
mapper.enableDefaultTyping(DefaultTyping.EVERYTHING, As.PROPERTY);
145146

146147
GenericJackson2JsonRedisSerializer.registerNullValueSerializer(mapper, null);
147148
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(mapper);
148149

149150
serializeAndDeserializeNullValue(serializer);
150151
}
151152

153+
@Test // GH-1566
154+
void deserializeShouldBeAbleToRestoreFinalObjectAfterSerialization() {
155+
156+
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
157+
158+
FinalObject source = new FinalObject();
159+
source.longValue = 1L;
160+
source.simpleObject = new SimpleObject(2L);
161+
162+
assertThat(serializer.deserialize(serializer.serialize(source))).isEqualTo(source);
163+
}
164+
152165
private static void serializeAndDeserializeNullValue(GenericJackson2JsonRedisSerializer serializer) {
153166

154167
NullValue nv = BeanUtils.instantiateClass(NullValue.class);
@@ -201,6 +214,12 @@ public boolean equals(Object obj) {
201214

202215
}
203216

217+
@Data
218+
static final class FinalObject {
219+
public Long longValue;
220+
SimpleObject simpleObject;
221+
}
222+
204223
static class SimpleObject {
205224

206225
public Long longValue;

0 commit comments

Comments
 (0)