jackson-databind
jackson-databind copied to clipboard
The `KeyDeserializer` specified in the class with `@JsonDeserialize(keyUsing = ...)` is overwritten by the `KeyDeserializer` specified in the `ObjectMapper`.
Search before asking
- [X] I searched in the issues and found nothing similar.
Describe the bug
SSIA
Also, the attached Java
reproduction code is directly adding KeyDeserializer
to SimpleModule
, but it seemed to be reproduced when using KeyDeserializers
.
Version Information
Reproduced in the latest 2.17 branch(fe42cf7). Also, 2.16.1 seems to have the same problem.
Reproduction
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class KeyDeserializerOverwritten {
@JsonDeserialize(keyUsing = ForClass.class)
static class MyKey {
private final String value;
MyKey(String value) {
this.value = value;
}
}
static class ForClass extends KeyDeserializer {
@Override
public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
return new MyKey(key + "-class");
}
}
static class ForMapper extends KeyDeserializer {
@Override
public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
return new MyKey(key + "-mapper");
}
}
TypeReference<Map<MyKey, String>> typeRef = new TypeReference<>() {};
@Test
void notCustom() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Map<MyKey, String> result = mapper.readValue("{\"foo\":null}", typeRef);
// OK
assertEquals("foo-class", result.keySet().stream().findFirst().get().value);
}
@Test
void addKeyDeserializer() throws JsonProcessingException {
SimpleModule sm = new SimpleModule();
sm.addKeyDeserializer(MyKey.class, new ForMapper());
ObjectMapper mapper = new ObjectMapper().registerModule(sm);
Map<MyKey, String> result = mapper.readValue("{\"foo\":null}", typeRef);
// NG
assertEquals("foo-class", result.keySet().stream().findFirst().get().value);
}
}
Expected behavior
Like JsonDeserializer
, the KeyDeserializer
specified for the class must be used.
Additional context
This problem was discovered during prototyping to solve https://github.com/FasterXML/jackson-module-kotlin/issues/777. https://github.com/ProjectMapK/jackson-module-kogera/pull/224
I'm not sure if I should merge it into kotlin-module
as it is, since the default content provided by KotlinModule
overrides any user customization.