jackson-databind
jackson-databind copied to clipboard
A reproduction of a Jackson deserializer Exception wrt `@JsonIgnoreProperties` on field
Jackson Version: jackson-databind:2.11.1
How to reproduce: Check out repo: https://github.com/r9liucc/jackson-deserializer-bug and run main class TestDeser.java, it will throw:
com.fasterxml.jackson.databind.exc.MismatchedInputException: No _valueDeserializer assigned
If rename Room.something to Room.outer, code will work.
With a quick look in the source code, I found that the hashcode of the field name impacts the deserializers initialization order, then the usage of type inheritance and circular reference will be problematic.
Possible dup of #1622 or #1755.
Does not occur in master, i.e. fixed for 3.0, but won't really help much with 2.x (side-effect of some refactoring but not easy to isolate).
I figured out the difference 3.x has, it is due to iterator() ordering for BeanPropertyMap; 3.x bases it on _propsInOrder and not hash area.
Unfortunately this is not actual fix, just working around the issue in this specific case and not really preventing it (can easily test by changing declaration order of fields). Looks like there is some bigger problem wrt transitive contextualization, I think, which does not sound very promising.
After trying to wrap my brain around the problem, I think I finally know how to tackle this problem.
The issue is due to combination of cyclic dependency and need to contextualize back-reference to partially resolved version of Room. Although in theory reordering of fields could work around the issue there just does not seem to be any good way to figure out better order. However, call to DeserializerCache knows the case when a "back reference" is made to partially initialized deserializer and ideally caller would then postpone contextualization -- with the help of DeserializerCache. But orchestrating this to happen requires careful sequencing of things within resolve() of BeanDeserializerBase, to extract out contextualization call and determining regular vs unusual case, and in latter getting a later call somehow at the point where call is safe to make.
Agree. I found that after Room has been resolve(), its BeanDeserializer was not flushed to the Building's BeanDeserializer, which means the deserializer of Room property wasn't updated in the Building's BeanDeserializer and it was still a FailingDeserializer for Room.id.