Skip to content

Commit f10f9f5

Browse files
committed
Rename predicate and action.
1 parent 2a128aa commit f10f9f5

8 files changed

Lines changed: 263 additions & 204 deletions
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright 2026-present 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.redis.serializer;
17+
18+
import java.lang.reflect.Modifier;
19+
import java.util.function.Predicate;
20+
import org.springframework.util.ClassUtils;
21+
22+
/**
23+
* Policy that defines whether to include automatic type information for Jackson
24+
* for each serialized type.
25+
* <p>
26+
* Provides a {@link Builder builder} to create a composite policy consisting of
27+
* outcomes to apply for individual types.
28+
* <p>
29+
* An example that uses the default policy and adds a rule for a custom type:
30+
* <pre class="code">
31+
* DefaultTypingPolicy.defaults()
32+
* .include((clazz) -> clazz == Person.class)
33+
* .build();
34+
* </pre>
35+
* <p>
36+
* This is a {@link FunctionalInterface} whose functional method is
37+
* {@link #outcomeForType(Class)}.
38+
*
39+
* @author Chris Bono
40+
* @since 4.1
41+
*/
42+
public interface DefaultTypingPolicy {
43+
44+
/**
45+
* The outcome to apply for a given type.
46+
*/
47+
enum Outcome {
48+
49+
/** Include type hints for the given type */
50+
INCLUDE_TYPE_HINT,
51+
52+
/** Do not include type hints for the given type */
53+
EXCLUDE_TYPE_HINT,
54+
55+
/** No opinion for the given type - fallback to the default logic */
56+
NO_OPINION;
57+
}
58+
59+
/**
60+
* Determine the outcome to take for a particular type.
61+
* @param clazz the type to check.
62+
* @return the outcome for the type.
63+
*/
64+
Outcome outcomeForType(Class<?> clazz);
65+
66+
/**
67+
* Obtain a builder with no defaults configured.
68+
* @return a builder with no defaults configured.
69+
*/
70+
static DefaultTypingPolicy.Builder empty() {
71+
return new StdDefaultTypingPolicy.DefaultBuilder();
72+
}
73+
74+
/**
75+
* Obtain a builder with defaults configured.
76+
* @return a builder with defaults configured.
77+
*/
78+
static DefaultTypingPolicy.Builder defaults() {
79+
80+
DefaultTypingPolicy.Builder builder = new StdDefaultTypingPolicy.DefaultBuilder();
81+
builder.include((clazz) -> clazz == Object.class);
82+
builder.exclude((clazz) -> Modifier.isFinal(clazz.getModifiers()) && clazz.getPackageName().startsWith("java"));
83+
builder.exclude(ClassUtils::isPrimitiveOrWrapper);
84+
builder.include(Class::isEnum);
85+
builder.include(Class::isRecord);
86+
87+
return builder;
88+
}
89+
90+
/**
91+
* A mutable builder for creating a {@link DefaultTypingPolicy}.
92+
*/
93+
interface Builder {
94+
95+
/**
96+
* Adds a rule that will return an {@link Outcome#INCLUDE_TYPE_HINT} outcome
97+
* for matching types.
98+
* @param typeMatcher the predicate to match the types.
99+
* @return this.
100+
*/
101+
Builder include(Predicate<Class<?>> typeMatcher);
102+
103+
/**
104+
* Adds a rule that will return an {@link Outcome#EXCLUDE_TYPE_HINT} outcome
105+
* for matching types.
106+
* @param typeMatcher the predicate to match the types.
107+
* @return this.
108+
*/
109+
Builder exclude(Predicate<Class<?>> typeMatcher);
110+
111+
/**
112+
* Adds a rule that will return an {@link Outcome#NO_OPINION} outcome
113+
* for matching types.
114+
* @param typeMatcher the predicate to match the types.
115+
* @return this.
116+
*/
117+
Builder fallback(Predicate<Class<?>> typeMatcher);
118+
119+
/**
120+
* Build the policy.
121+
* @return the policy.
122+
*/
123+
DefaultTypingPolicy build();
124+
}
125+
126+
}

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

Lines changed: 0 additions & 80 deletions
This file was deleted.

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ private static Lazy<String> getConfiguredTypeDeserializationPropertyName(ObjectM
215215
});
216216
}
217217

218-
private static StdTypeResolverBuilder createDefaultTypeResolverBuilder(@Nullable DefaultTypingPredicate defaultTyping,
218+
private static StdTypeResolverBuilder createDefaultTypeResolverBuilder(@Nullable DefaultTypingPolicy defaultTyping,
219219
ObjectMapper objectMapper,
220220
@Nullable String typeHintPropertyName) {
221221

@@ -475,7 +475,7 @@ public static class GenericJackson2JsonRedisSerializerBuilder {
475475

476476
private @Nullable Boolean defaultTypingEnabled;
477477

478-
private @Nullable DefaultTypingPredicate defaultTyping;
478+
private @Nullable DefaultTypingPolicy defaultTyping;
479479

480480
private boolean registerNullValueSerializer = true;
481481

@@ -507,7 +507,7 @@ public GenericJackson2JsonRedisSerializerBuilder defaultTyping(boolean defaultTy
507507
* @return this {@link GenericJackson2JsonRedisSerializer.GenericJackson2JsonRedisSerializerBuilder}.
508508
* @since 4.0.4
509509
*/
510-
public GenericJackson2JsonRedisSerializerBuilder defaultTyping(DefaultTypingPredicate defaultTyping) {
510+
public GenericJackson2JsonRedisSerializerBuilder defaultTyping(DefaultTypingPolicy defaultTyping) {
511511
this.defaultTypingEnabled = true;
512512
this.defaultTyping = defaultTyping;
513513
return this;
@@ -640,15 +640,15 @@ public GenericJackson2JsonRedisSerializer build() {
640640
*/
641641
private static class TypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
642642

643-
private final @Nullable DefaultTypingPredicate defaultTyping;
643+
private final @Nullable DefaultTypingPolicy defaultTyping;
644644

645-
static TypeResolverBuilder forTyping(@Nullable DefaultTypingPredicate defaultTyping, ObjectMapper mapper) {
645+
static TypeResolverBuilder forTyping(@Nullable DefaultTypingPolicy defaultTyping, ObjectMapper mapper) {
646646
return new TypeResolverBuilder(
647647
defaultTyping,
648648
mapper.getPolymorphicTypeValidator());
649649
}
650650

651-
public TypeResolverBuilder(@Nullable DefaultTypingPredicate defaultTyping, PolymorphicTypeValidator polymorphicTypeValidator) {
651+
public TypeResolverBuilder(@Nullable DefaultTypingPolicy defaultTyping, PolymorphicTypeValidator polymorphicTypeValidator) {
652652
super(DefaultTyping.EVERYTHING, polymorphicTypeValidator);
653653
this.defaultTyping = defaultTyping;
654654
}
@@ -669,15 +669,15 @@ public boolean useForType(JavaType javaType) {
669669
JavaType resolvedType = resolveArrayOrWrapper(javaType);
670670
Class<?> rawClass = resolvedType.getRawClass();
671671

672-
DefaultTypingPredicate typingPredicate = defaultTyping != null ? defaultTyping :
673-
DefaultTypingPredicate.defaults().build();
672+
DefaultTypingPolicy typingPredicate = defaultTyping != null ? defaultTyping :
673+
DefaultTypingPolicy.defaults().build();
674674

675-
DefaultTypingPredicate.Action action = typingPredicate.test(rawClass);
675+
DefaultTypingPolicy.Outcome action = typingPredicate.outcomeForType(rawClass);
676676

677677
return switch (action) {
678-
case YES -> true;
679-
case NO -> false;
680-
case DONT_CARE -> !TreeNode.class.isAssignableFrom(rawClass);
678+
case INCLUDE_TYPE_HINT -> true;
679+
case EXCLUDE_TYPE_HINT -> false;
680+
case NO_OPINION -> !TreeNode.class.isAssignableFrom(rawClass);
681681
};
682682
}
683683

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ public static class GenericJacksonJsonRedisSerializerBuilder<B extends MapperBui
266266

267267
private boolean cacheNullValueSupportEnabled = false;
268268
private boolean defaultTypingEnabled;
269-
private @Nullable DefaultTypingPredicate defaultTyping;
269+
private @Nullable DefaultTypingPolicy defaultTyping;
270270
private @Nullable String typePropertyName;
271271
private PolymorphicTypeValidator typeValidator = BasicPolymorphicTypeValidator.builder()
272272
.allowIfBaseType(Object.class).allowIfSubType((ctx, clazz) -> true).build();
@@ -320,7 +320,7 @@ public GenericJacksonJsonRedisSerializerBuilder<B> enableSpringCacheNullValueSup
320320
* @see <a href=
321321
* "https://owasp.org/www-community/vulnerabilities/Deserialization_of_untrusted_data">https://owasp.org/www-community/vulnerabilities/Deserialization_of_untrusted_data</a>
322322
*/
323-
@Contract("_ -> this")
323+
@Contract("-> this")
324324
public GenericJacksonJsonRedisSerializerBuilder<B> enableUnsafeDefaultTyping() {
325325

326326
this.defaultTypingEnabled = true;
@@ -356,7 +356,7 @@ public GenericJacksonJsonRedisSerializerBuilder<B> enableDefaultTyping(Polymorph
356356
* @return {@code this} builder.
357357
*/
358358
@Contract("_ -> this")
359-
public GenericJacksonJsonRedisSerializerBuilder<B> defaultTyping(DefaultTypingPredicate defaultTyping) {
359+
public GenericJacksonJsonRedisSerializerBuilder<B> defaultTyping(DefaultTypingPolicy defaultTyping) {
360360

361361
this.defaultTypingEnabled = true;
362362
this.defaultTyping = defaultTyping;
@@ -617,9 +617,9 @@ public void setupModule(SetupContext context) {
617617

618618
private static class TypeResolverBuilder extends DefaultTypeResolverBuilder {
619619

620-
private final @Nullable DefaultTypingPredicate defaultTyping;
620+
private final @Nullable DefaultTypingPolicy defaultTyping;
621621

622-
public TypeResolverBuilder(PolymorphicTypeValidator subtypeValidator, @Nullable DefaultTypingPredicate defaultTyping,
622+
public TypeResolverBuilder(PolymorphicTypeValidator subtypeValidator, @Nullable DefaultTypingPolicy defaultTyping,
623623
JsonTypeInfo.As includeAs,
624624
JsonTypeInfo.Id idType, @Nullable String propertyName) {
625625
super(subtypeValidator, DefaultTyping.NON_FINAL, includeAs, idType, propertyName);
@@ -642,15 +642,15 @@ public boolean useForType(JavaType javaType) {
642642
JavaType resolvedType = resolveArrayOrWrapper(javaType);
643643
Class<?> rawClass = resolvedType.getRawClass();
644644

645-
DefaultTypingPredicate typingPredicate = defaultTyping != null ? defaultTyping :
646-
DefaultTypingPredicate.defaults().build();
645+
DefaultTypingPolicy typingPredicate = defaultTyping != null ? defaultTyping :
646+
DefaultTypingPolicy.defaults().build();
647647

648-
DefaultTypingPredicate.Action action = typingPredicate.test(rawClass);
648+
DefaultTypingPolicy.Outcome action = typingPredicate.outcomeForType(rawClass);
649649

650650
return switch (action) {
651-
case YES -> true;
652-
case NO -> false;
653-
case DONT_CARE -> !TreeNode.class.isAssignableFrom(rawClass);
651+
case INCLUDE_TYPE_HINT -> true;
652+
case EXCLUDE_TYPE_HINT -> false;
653+
case NO_OPINION -> !TreeNode.class.isAssignableFrom(rawClass);
654654
};
655655
}
656656

0 commit comments

Comments
 (0)