2525import com .fasterxml .jackson .annotation .JsonTypeInfo ;
2626import com .fasterxml .jackson .annotation .JsonTypeInfo .As ;
2727import com .fasterxml .jackson .core .JsonGenerator ;
28- import com .fasterxml .jackson .core .JsonProcessingException ;
2928import com .fasterxml .jackson .databind .ObjectMapper ;
3029import com .fasterxml .jackson .databind .ObjectMapper .DefaultTyping ;
3130import com .fasterxml .jackson .databind .SerializerProvider ;
3736
3837/**
3938 * Generic Jackson 2-based {@link RedisSerializer} that maps {@link Object objects} to JSON using dynamic typing.
39+ * <p>
40+ * JSON reading and writing can be customized by configuring {@link JacksonObjectReader} respective
41+ * {@link JacksonObjectWriter}.
4042 *
4143 * @author Christoph Strobl
4244 * @author Mark Paluch
@@ -47,6 +49,10 @@ public class GenericJackson2JsonRedisSerializer implements RedisSerializer<Objec
4749
4850 private final ObjectMapper mapper ;
4951
52+ private final JacksonObjectReader reader ;
53+
54+ private final JacksonObjectWriter writer ;
55+
5056 /**
5157 * Creates {@link GenericJackson2JsonRedisSerializer} and configures {@link ObjectMapper} for default typing.
5258 */
@@ -59,13 +65,30 @@ public GenericJackson2JsonRedisSerializer() {
5965 * given {@literal name}. In case of an {@literal empty} or {@literal null} String the default
6066 * {@link JsonTypeInfo.Id#CLASS} will be used.
6167 *
62- * @param classPropertyTypeName Name of the JSON property holding type information. Can be {@literal null}.
68+ * @param classPropertyTypeName name of the JSON property holding type information. Can be {@literal null}.
6369 * @see ObjectMapper#activateDefaultTypingAsProperty(PolymorphicTypeValidator, DefaultTyping, String)
6470 * @see ObjectMapper#activateDefaultTyping(PolymorphicTypeValidator, DefaultTyping, As)
6571 */
6672 public GenericJackson2JsonRedisSerializer (@ Nullable String classPropertyTypeName ) {
73+ this (classPropertyTypeName , JacksonObjectReader .create (), JacksonObjectWriter .create ());
74+ }
75+
76+ /**
77+ * Creates {@link GenericJackson2JsonRedisSerializer} and configures {@link ObjectMapper} for default typing using the
78+ * given {@literal name}. In case of an {@literal empty} or {@literal null} String the default
79+ * {@link JsonTypeInfo.Id#CLASS} will be used.
80+ *
81+ * @param classPropertyTypeName name of the JSON property holding type information. Can be {@literal null}.
82+ * @param reader the {@link JacksonObjectReader} function to read objects using {@link ObjectMapper}.
83+ * @param writer the {@link JacksonObjectWriter} function to write objects using {@link ObjectMapper}.
84+ * @see ObjectMapper#activateDefaultTypingAsProperty(PolymorphicTypeValidator, DefaultTyping, String)
85+ * @see ObjectMapper#activateDefaultTyping(PolymorphicTypeValidator, DefaultTyping, As)
86+ * @since 3.0
87+ */
88+ public GenericJackson2JsonRedisSerializer (@ Nullable String classPropertyTypeName , JacksonObjectReader reader ,
89+ JacksonObjectWriter writer ) {
6790
68- this (new ObjectMapper ());
91+ this (new ObjectMapper (), reader , writer );
6992
7093 // simply setting {@code mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)} does not help here since we need
7194 // the type hint embedded for deserialization using the default typing feature.
@@ -87,9 +110,29 @@ public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName
87110 * @param mapper must not be {@literal null}.
88111 */
89112 public GenericJackson2JsonRedisSerializer (ObjectMapper mapper ) {
113+ this (mapper , JacksonObjectReader .create (), JacksonObjectWriter .create ());
114+ }
115+
116+ /**
117+ * Setting a custom-configured {@link ObjectMapper} is one way to take further control of the JSON serialization
118+ * process. For example, an extended {@link SerializerFactory} can be configured that provides custom serializers for
119+ * specific types.
120+ *
121+ * @param mapper must not be {@literal null}.
122+ * @param reader the {@link JacksonObjectReader} function to read objects using {@link ObjectMapper}.
123+ * @param writer the {@link JacksonObjectWriter} function to write objects using {@link ObjectMapper}.
124+ * @since 3.0
125+ */
126+ public GenericJackson2JsonRedisSerializer (ObjectMapper mapper , JacksonObjectReader reader ,
127+ JacksonObjectWriter writer ) {
90128
91129 Assert .notNull (mapper , "ObjectMapper must not be null" );
130+ Assert .notNull (reader , "Reader must not be null" );
131+ Assert .notNull (writer , "Writer must not be null" );
132+
92133 this .mapper = mapper ;
134+ this .reader = reader ;
135+ this .writer = writer ;
93136 }
94137
95138 /**
@@ -116,8 +159,8 @@ public byte[] serialize(@Nullable Object source) throws SerializationException {
116159 }
117160
118161 try {
119- return mapper . writeValueAsBytes ( source );
120- } catch (JsonProcessingException e ) {
162+ return writer . write ( mapper , source );
163+ } catch (IOException e ) {
121164 throw new SerializationException ("Could not write JSON: " + e .getMessage (), e );
122165 }
123166 }
@@ -134,6 +177,7 @@ public Object deserialize(@Nullable byte[] source) throws SerializationException
134177 * @throws SerializationException
135178 */
136179 @ Nullable
180+ @ SuppressWarnings ("unchecked" )
137181 public <T > T deserialize (@ Nullable byte [] source , Class <T > type ) throws SerializationException {
138182
139183 Assert .notNull (type ,
@@ -144,7 +188,7 @@ public <T> T deserialize(@Nullable byte[] source, Class<T> type) throws Serializ
144188 }
145189
146190 try {
147- return mapper . readValue ( source , type );
191+ return ( T ) reader . read ( mapper , source , mapper . getTypeFactory (). constructType ( type ) );
148192 } catch (Exception ex ) {
149193 throw new SerializationException ("Could not read JSON: " + ex .getMessage (), ex );
150194 }
@@ -172,8 +216,7 @@ private static class NullValueSerializer extends StdSerializer<NullValue> {
172216 }
173217
174218 @ Override
175- public void serialize (NullValue value , JsonGenerator jgen , SerializerProvider provider )
176- throws IOException {
219+ public void serialize (NullValue value , JsonGenerator jgen , SerializerProvider provider ) throws IOException {
177220
178221 jgen .writeStartObject ();
179222 jgen .writeStringField (classIdentifier , NullValue .class .getName ());
@@ -186,4 +229,5 @@ public void serializeWithType(NullValue value, JsonGenerator gen, SerializerProv
186229 serialize (value , gen , serializers );
187230 }
188231 }
232+
189233}
0 commit comments