Description
Search before asking
- I searched in the issues and found nothing similar.
Describe the bug
I am currently migrating from Jackson version 2.10.0 to 2.15.1 and I seem to be encountering a bug. When attempting to deserialize JSON into a POJO, a JsonMappingException (Cf. Stacktrace below) is thrown for the age field in the simplified code snippet provided below. The same code works perfectly with version 2.10.0.
Version Information
2.15.2
Reproduction
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import java.io.IOException;
class Person {
public String id;
public String name;
public Long age;
}
class MongoTypeProblemHandler extends DeserializationProblemHandler {
protected static final String NUMBER_LONG_KEY = "$numberLong";
@Override
public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException {
if (targetType.getRawClass().equals(Long.class) && JsonToken.START_OBJECT.equals(t)) {
JsonNode tree = p.readValueAsTree();
if (tree.get(NUMBER_LONG_KEY) != null) {
try {
return Long.parseLong(tree.get(NUMBER_LONG_KEY).asText());
} catch (NumberFormatException e) {
}
}
}
return NOT_HANDLED;
}
}
public class Main {
public static void main(String[] args) {
String json = "{\"id\": \"12ab\", \"name\": \"Bob\", \"age\": {\"$numberLong\": \"10\"}}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.addHandler(new MongoTypeProblemHandler());
try {
Person person = objectMapper.readValue(json, Person.class);
System.out.println("id:" + person.id);
System.out.println("name:" + person.name);
System.out.println("age:" + person.age);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
Expected behavior
It should deserialize the JSON to POJO like version 2.10.0 for example
Additional context
Exception in thread "main" java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: class java.lang.Long cannot be cast to class java.lang.String (java.lang.Long and java.lang.String are in module java.base of loader 'bootstrap') (through reference chain: org.example.Person["age"])
at org.example.Main.main(Main.java:50)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: class java.lang.Long cannot be cast to class java.lang.String (java.lang.Long and java.lang.String are in module java.base of loader 'bootstrap') (through reference chain: org.example.Person["age"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:402)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:361)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1853)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:316)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3772)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3740)
at org.example.Main.main(Main.java:45)
Caused by: java.lang.ClassCastException: class java.lang.Long cannot be cast to class java.lang.String (java.lang.Long and java.lang.String are in module java.base of loader 'bootstrap')
at com.fasterxml.jackson.databind.DeserializationContext.extractScalarFromObject(DeserializationContext.java:943)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseLong(StdDeserializer.java:949)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$LongDeserializer.deserialize(NumberDeserializers.java:575)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$LongDeserializer.deserialize(NumberDeserializers.java:550)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
... 6 more