From 0ee3a0600f6956d142d9c8b01f5f7cfeeceff7d0 Mon Sep 17 00:00:00 2001 From: MinJun Choi Date: Mon, 17 Nov 2025 01:37:24 +0900 Subject: [PATCH] Add static factory method for JacksonJsonRedisSerializer. Introduces JacksonJsonRedisSerializer.of(Class) as a static factory method for creating serializer instances, and adds RedisSerializer.json(Class) as an interface-level helper method. This simplifies RedisTemplate setup code and aligns with modern Java API design conventions. Closes #3252 Signed-off-by: Minjun Choi --- .../JacksonJsonRedisSerializer.java | 14 ++++ .../redis/serializer/RedisSerializer.java | 16 ++++ .../JacksonJsonRedisSerializerUnitTests.java | 84 +++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerUnitTests.java diff --git a/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java index bb4bd2e5a8..10589d31cc 100644 --- a/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializer.java @@ -50,6 +50,20 @@ public class JacksonJsonRedisSerializer implements RedisSerializer { private final JacksonObjectWriter writer; + /** + * Creates a new {@link JacksonJsonRedisSerializer} for the given target {@link Class}. + *

+ * This is a convenience factory method equivalent to calling the constructor directly. + * + * @param type must not be {@literal null}. + * @param the target type. + * @return new instance of {@link JacksonJsonRedisSerializer}. Never {@literal null}. + * @since 4.0 + */ + public static JacksonJsonRedisSerializer of(Class type) { + return new JacksonJsonRedisSerializer<>(type); + } + /** * Creates a new {@link JacksonJsonRedisSerializer} for the given target {@link Class}. * diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java index 5f3b232782..204164ac53 100644 --- a/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java @@ -65,6 +65,22 @@ static RedisSerializer json() { .create(it -> it.enableSpringCacheNullValueSupport().enableUnsafeDefaultTyping()); } + /** + * Obtain a {@link RedisSerializer} that can read and write JSON using + * Jackson for a specific type. + *

+ * Unlike {@link #json()} which uses default typing, this method creates a type-safe serializer + * bound to the given class. + * + * @param type must not be {@literal null}. + * @param the target type. + * @return never {@literal null}. + * @since 4.0 + */ + static RedisSerializer json(Class type) { + return new JacksonJsonRedisSerializer<>(type); + } + /** * Obtain a simple {@link java.lang.String} to {@code byte[]} (and back) serializer using * {@link java.nio.charset.StandardCharsets#UTF_8 UTF-8} as the default {@link java.nio.charset.Charset}. diff --git a/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerUnitTests.java b/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerUnitTests.java new file mode 100644 index 0000000000..0032cdcc57 --- /dev/null +++ b/src/test/java/org/springframework/data/redis/serializer/JacksonJsonRedisSerializerUnitTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2025 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.redis.serializer; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +import org.springframework.data.redis.Person; +import org.springframework.data.redis.PersonObjectFactory; + +/** + * Unit tests for {@link JacksonJsonRedisSerializer}. + * + * @author Minjun Choi + */ +class JacksonJsonRedisSerializerUnitTests { + + @Test // GH-3252 + void ofShouldCreateSerializerForGivenType() { + + JacksonJsonRedisSerializer serializer = JacksonJsonRedisSerializer.of(Person.class); + + assertThat(serializer).isNotNull(); + + Person person = new PersonObjectFactory().instance(); + byte[] serialized = serializer.serialize(person); + Person deserialized = serializer.deserialize(serialized); + + assertThat(deserialized).isEqualTo(person); + } + + @Test // GH-3252 + void redisSerializerJsonShouldCreateSerializerForGivenType() { + + RedisSerializer serializer = RedisSerializer.json(Person.class); + + assertThat(serializer).isNotNull(); + assertThat(serializer).isInstanceOf(JacksonJsonRedisSerializer.class); + + Person person = new PersonObjectFactory().instance(); + byte[] serialized = serializer.serialize(person); + Person deserialized = serializer.deserialize(serialized); + + assertThat(deserialized).isEqualTo(person); + } + + @Test // GH-3252 + void serializeShouldReturnEmptyByteArrayWhenSourceIsNull() { + + JacksonJsonRedisSerializer serializer = JacksonJsonRedisSerializer.of(Person.class); + + assertThat(serializer.serialize(null)).isEqualTo(SerializationUtils.EMPTY_ARRAY); + } + + @Test // GH-3252 + void deserializeShouldReturnNullWhenSourceIsNull() { + + JacksonJsonRedisSerializer serializer = JacksonJsonRedisSerializer.of(Person.class); + + assertThat(serializer.deserialize(null)).isNull(); + } + + @Test // GH-3252 + void deserializeShouldReturnNullWhenSourceIsEmptyArray() { + + JacksonJsonRedisSerializer serializer = JacksonJsonRedisSerializer.of(Person.class); + + assertThat(serializer.deserialize(SerializationUtils.EMPTY_ARRAY)).isNull(); + } +}