FasterXML / jackson-databind

General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
Apache License 2.0
3.53k stars 1.38k forks source link

activateDefaultTyping and JsonDeserialize(converter do not work on Date fields #3639

Open craftmaster2190 opened 2 years ago

craftmaster2190 commented 2 years ago

Describe the bug When using objectMapper.activateDefaultTyping and @JsonDeserialize(converter = ...) on a Date field, Jackson perhaps incorrectly serializes a Long as ["java.lang.Long",1234567890000] (I would have expected 1234567890000), and throws an exception instead of deserializing.

Throws:

com.fasterxml.jackson.databind.exc.MismatchedInputException:
Cannot deserialize value of type `java.lang.Long` from Array value (token `JsonToken.START_ARRAY`)
at [Source: (String)"{"@class":"com.example.jacksonbug.DateReference","date":["java.lang.Long",1666213651605]}";
line: 1, column: 57] (through reference chain: com.example.jacksonbug.DateReference["date"])

However, the same bug does not appear with other types. If I put a @JsonDeserialize(converter = ...) on a custom type, jackson serializes/deserializes correctly.

I've included a repo to reproduce both scenarios.

Version information Discovered in jackson-databind 2.13.4 Also reproducible in jackson-databind 2.14.0-rc2

To Reproduce Run the main method here: https://github.com/craftmaster2190/jackson-date-converter-bug

cowtowncoder commented 2 years ago

Ok, first things first: the reason why long / Long handling differs from other types is due to "long" being one of a small number of "natural" types, for which type information is never to be included (as an optimization -- in hindsight, possibly not a good idea). Other natural types are String, boolean/Boolean, double/Double.

But in this case use of Converter is probably problematic: if the nominal/declared type is Date there is probably discrepancy between handling somewhere (for Long no type id can/should be written/expected to read; for Date type id should be written and read).

At any rate, handling is wrong; it should either:

I think latter would be the correct behavior. But fundamentally use of Converters is challenging with Polymorphic Typing since the idea is that there is this "intermediate" convenience type and then routing of calls for TypeSerializer/JsonSerializer and TypeDeserializer/JsonDeserializer (first of pair handling Type Id, second actual value once type is written/read) needs to translate calls in proper way. So while it'd be good to fix this, I would also recommend considering this combination of features problematic and if possible finding another way to achieve the same result: possibly custom serializer (and likely deserializer) instead of converter-based one.

I hope to look into this deeper in future, but thought I'd add a note now (I have 2.14 release tasks to focus on but going through all issue reports as well).