Existing object of local/anonymous class cannot be updated
When using readerForUpdating with an existing object, Jackson fails with:
Cannot deserialize Class mypackage.MyClass$1 (of type local/anonymous) as a Bean
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.isPotentialBeanType(BeanDeserializerFactory.java:883)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:137)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:414)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
Version information 2.10.3
To Reproduce
package mypackage;
public class MyClass {
public static void main(int[] args) {
Object resultObject = new Object() {
int value;
}
new ObjectMapper().readerForUpdating(resultObject).readValue("{\"value\": 2}");
}
}
Expected behavior Since Jackson is not required to construct an instance of the anonymous class, it should be able to populate the fields on the existing object. Investigation shows that the method
public Object deserialize(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException
in com.fasterxml.jackson.databind.deser.BeanDeserializer doesn't use ValueInstantiator _valueInstantiator field.
So can it be made optional when you're updating an existing instance?
Workaround that worked for me was to write a custom deserializer and simply exclude the validation code:
protected static class CustomDeserializer<T> extends JsonDeserializer<T> {
@Override
public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
throw new IllegalStateException("Unsupported");
}
@Override
@SuppressWarnings("unchecked")
public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue) throws IOException {
JavaType javaType = ctxt.getTypeFactory().constructType(intoValue.getClass());
JsonDeserializer<T> jsonDeserializer = (JsonDeserializer<T>) ((BeanDeserializerFactory) ctxt.getFactory())
.buildBeanDeserializer(ctxt, javaType, ctxt.getConfig().introspect(javaType));
((ResolvableDeserializer) jsonDeserializer).resolve(ctxt);
jsonDeserializer = (JsonDeserializer<T>) ctxt.handleSecondaryContextualization(jsonDeserializer, null, javaType);
return jsonDeserializer.deserialize(p, ctxt, intoValue);
}
}
Would definitely be nice to support this at some point in future.