-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Closed as not planned
Closed as not planned
Copy link
Labels
status: supersededAn issue that has been superseded by anotherAn issue that has been superseded by another
Description
📌 Summary
GenericJackson2JsonRedisSerializer.TypeResolvercurrently creates a newObjectMapperinstead of using an existing one.- This leads to issues where users cannot apply custom configurations like
StreamReadConstraintsfor handling large JSON strings. - Even when explicitly setting
ObjectMapperwithmaxStringLength = 100MB, theTypeResolverstill enforces a 20MB limit, causing deserialization failures.
🔍 Steps to Reproduce
- Configure a custom
ObjectMapperwithStreamReadConstraints.maxStringLength = 100MB - Use
GenericJackson2JsonRedisSerializerfor Redis serialization - Store a large JSON object (e.g., 50MB) in Redis
- Attempt to retrieve the JSON using
RedisTemplateor@Cacheable - Observe that
TypeResolvercreates 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
TypeResolvershould use the configuredObjectMapperinstead of creating a new one internally.- Custom
StreamReadConstraints.maxStringLength = 100MBshould be respected when deserializing Redis data.
🛠 Suggested Fix
- Modify
TypeResolverto accept anObjectMapperinstance 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.
hyunjoo-yi and bgcho98
Metadata
Metadata
Assignees
Labels
status: supersededAn issue that has been superseded by anotherAn issue that has been superseded by another