`GenericJackson3JsonRedisSerializer` is throwing exception when deserializing a Collection when defaultTyping is enabled
Closed this issue · 6 comments
Hello!
Spring Boot Version: 4.0.0-M3
Java: 25
I have an issue when trying to deserialize a String with type information. For example
private static final String JSON_STRING ="""
["java.util.ArrayList",[{"@class":"com.example.redisdemo.RedisdemoApplicationTests$Person","firstName":"firstName","lastName":"lastName"}]]
""";When trying to deserialize the object, an exception is throw when trying to resolve the type. This works with GenericJackson2JsonRedisSerializer.
This is the stacktrace when running a test
[ERROR] com.example.redisdemo.RedisdemoApplicationTests.genericJackson3JsonRedisSerializerTest -- Time elapsed: 0.180 s <<< ERROR!
org.springframework.data.redis.serializer.SerializationException: Could not read JSON:Cannot invoke "tools.jackson.databind.JsonNode.isString()" because "jsonNode" is null
at org.springframework.data.redis.serializer.GenericJackson3JsonRedisSerializer.deserialize(GenericJackson3JsonRedisSerializer.java:212)
at org.springframework.data.redis.serializer.GenericJackson3JsonRedisSerializer.deserialize(GenericJackson3JsonRedisSerializer.java:182)
at com.example.redisdemo.RedisdemoApplicationTests.genericJackson3JsonRedisSerializerTest(RedisdemoApplicationTests.java:47)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
Caused by: java.lang.NullPointerException: Cannot invoke "tools.jackson.databind.JsonNode.isString()" because "jsonNode" is null
at org.springframework.data.redis.serializer.GenericJackson3JsonRedisSerializer$TypeResolver.resolveType(GenericJackson3JsonRedisSerializer.java:482)
at org.springframework.data.redis.serializer.GenericJackson3JsonRedisSerializer.resolveType(GenericJackson3JsonRedisSerializer.java:222)
at org.springframework.data.redis.serializer.GenericJackson3JsonRedisSerializer.deserialize(GenericJackson3JsonRedisSerializer.java:210)
... 5 moreThis is the code being used to test the issue
private static final String JSON_STRING ="""
["java.util.ArrayList",[{"@class":"com.example.redisdemo.RedisdemoApplicationTests$Person","firstName":"firstName","lastName":"lastName"}]]
""";
private GenericJackson3JsonRedisSerializer createGenericJackson3JsonRedisSerializer() {
return GenericJackson3JsonRedisSerializer.builder()
.customize(builder -> builder
.activateDefaultTyping(
BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(Object.class)
.build(),
DefaultTyping.NON_FINAL,
As.PROPERTY)
.findAndAddModules())
.build();
}
@Test
void genericJackson3JsonRedisSerializerTest() {
var serializer = createGenericJackson3JsonRedisSerializer();
List<Person> listOfPerson = (List) serializer.deserialize(JSON_STRING.getBytes());
assertThat(listOfPerson)
.isNotEmpty()
.contains(new Person("firstName", "lastName"));
}I'm attaching a small application with a test using both GenericJackson2JsonRedisSerializer and GenericJackson3JsonRedisSerializer
Thanks!
thank you @andrew2184 for reporting and providing a reproducer.
Just adding to what @andrew2184 said it seems that the serialized value does not attach java.util.List class type to START_ARRAY token.
org.opentest4j.AssertionFailedError: expected: "["java.util.List",[{"@class":"com.example.redisdemo.RedisdemoApplicationTests$Person","firstName":"firstName","lastName":"lastName"},{"@class":"com.example.redisdemo.RedisdemoApplicationTests$Person","firstName":"firstName2","lastName":"lastName2"}]] " but was: "[{"@class":"com.example.redisdemo.RedisdemoApplicationTests$Person","firstName":"firstName","lastName":"lastName"},{"@class":"com.example.redisdemo.RedisdemoApplicationTests$Person","firstName":"firstName2","lastName":"lastName2"}]" <Click to see difference>
Let me know if its a misconfiguration. Also I confirm its is occurring in RC-1 version (same as @andrew2184 configured).
Attaching the same demo with the additional test.
Thank you guys for the awesome work
Hi @yurikilian. I had a look at your test and in your case, it's because you are using List.of() which will return java.util.Collections$UnmodifiableRandomAccessList which is final. Because we are using DefaultTyping.NON_FINAL, it won't add the type. It will work if you use a mutable class like ArrayList. Also, this is probably more on the side of Jackson. Thanks for having a look as well.
jeez good catch @andrew2184 . my bad. Thank you anyway
Just to add that with final configuration the same occurs. Aka, Cannot cache List for exemple.
hi @christophstrobl Sorry, I can see that this has been fixed in RC1. I think we can close this ticket. Also I saw that GenericJackson3JsonRedisSerializer was renamed to just GenericJacksonJsonRedisSerializer.