Closed as not planned
Closed as not planned
Description
📌 Summary
GenericJackson2JsonRedisSerializer.TypeResolver
currently creates a newObjectMapper
instead of using an existing one.- This leads to issues where users cannot apply custom configurations like
StreamReadConstraints
for handling large JSON strings. - Even when explicitly setting
ObjectMapper
withmaxStringLength = 100MB
, theTypeResolver
still enforces a 20MB limit, causing deserialization failures.
🔍 Steps to Reproduce
- Configure a custom
ObjectMapper
withStreamReadConstraints.maxStringLength = 100MB
- Use
GenericJackson2JsonRedisSerializer
for Redis serialization - Store a large JSON object (e.g., 50MB) in Redis
- Attempt to retrieve the JSON using
RedisTemplate
or@Cacheable
- Observe that
TypeResolver
creates a newObjectMapper
, which applies a 20MB limit, leading to:Could not read JSON:String value length (20054016) exceeds the maximum allowed (20000000, from `StreamReadConstraints.getMaxStringLength()`)
🚀 Expected Behavior
TypeResolver
should use the configuredObjectMapper
instead of creating a new one internally.- Custom
StreamReadConstraints.maxStringLength = 100MB
should be respected when deserializing Redis data.
🛠 Suggested Fix
- Modify
TypeResolver
to accept anObjectMapper
instance as a constructor argument. - If
null
, it should fall back to a default instance.
📎 Relevant Code (Current Issue)
static class TypeResolver {
private final ObjectMapper mapper = new ObjectMapper(); // ⚠️ Always creates a new ObjectMapper
private final Supplier<TypeFactory> typeFactory;
private final Supplier<String> hintName;
TypeResolver(Supplier<TypeFactory> typeFactory, Supplier<String> hintName) {
this.typeFactory = typeFactory;
this.hintName = hintName;
}
protected JavaType resolveType(byte[] source, Class<?> type) throws IOException {
JsonNode root = mapper.readTree(source);
JsonNode jsonNode = root.get(hintName.get());
if (jsonNode instanceof TextNode && jsonNode.asText() != null) {
return typeFactory.get().constructFromCanonical(jsonNode.asText());
}
return constructType(type);
}
}
✅ Suggested Fix
private final ObjectMapper mapper;
TypeResolver(Supplier<TypeFactory> typeFactory, Supplier<String> hintName, ObjectMapper objectMapper) {
this.typeFactory = typeFactory;
this.hintName = hintName;
this.mapper = (objectMapper != null) ? objectMapper : new ObjectMapper();
}
🌍 Environment
- Spring Boot: 3.3.6
- Jackson: 2.17.3
- Spring Data Redis: Latest
📢 Additional Context
This issue causes Redis deserialization failures when handling large JSON payloads. Users configuring a custom ObjectMapper
expect their settings to be respected, but TypeResolver
currently overrides them by always creating a new instance. Fixing this will ensure better configurability and prevent unexpected SerializationException
errors.