-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix failing double
JsonCreators in jackson 2.12.0
#2978
Fix failing double
JsonCreators in jackson 2.12.0
#2978
Conversation
747258b
to
9b61a42
Compare
a2q("{'double': 2.0,'type':'double'}"), | ||
new TypeReference<UnionExample>() {}); | ||
assertEquals(expected, actual); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test passes on 2.11 and fails on 2.12 with:
Cannot construct instance of
com.fasterxml.jackson.databind.jsontype.TestDoubleJsonCreator$AliasDouble
(although at least one Creator exists): no BigDecimal/double/Double-argument constructor/factory method to deserialize from Number value (2.0)
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.fasterxml.jackson.databind.jsontype.TestDoubleJsonCreator$AliasDouble` (although at least one Creator exists): no BigDecimal/double/Double-argument constructor/factory method to deserialize from Number value (2.0)
at [Source: (String)"{"double": 2.0,"type":"double"}"; line: 1, column: 23] (through reference chain: com.fasterxml.jackson.databind.jsontype.TestDoubleJsonCreator$UnionExample$DoubleWrapper["double"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1588)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1213)
at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromBigDecimal(ValueInstantiator.java:351)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromBigDecimal(StdValueInstantiator.java:463)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromDouble(BeanDeserializerBase.java:1518)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:211)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:197)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:565)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1390)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:230)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:197)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:135)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:105)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:263)
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1383)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3531)
at com.fasterxml.jackson.databind.jsontype.TestDoubleJsonCreator.testDeserializationTypeFieldLast(TestDoubleJsonCreator.java:216)
...
a2q("{'type':'double','double': 2.0}"), | ||
new TypeReference<UnionExample>() {}); | ||
assertEquals(expected, actual); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this test passes on both versions.
Quick comment: looking through the PR, I found a small bug with #2215 implementation (plus the fact that added tests did not actually exercise the changed code :-( ). I checked in a fix so you may want to merge from 2.12 (might require manual merge due to indentation). I wish changes here weren't needed since ideally we wouldn't add range checks and implicit coercions, but I'll have a look at tests to see what is happening. Buffering ( |
9b61a42
to
8ebe80b
Compare
I've rebased and re-pushed (it went cleanly) and I've verified the fix you pushed to 2.12 didn't impact my failing test. I don't have a reproducer for the long case, so it's possible that it's not necessary -- in the buffering case ideally we'd use the smallest possible type to represent a number. I added it to be defensive because the I'm not sure there's any path away from supporting BigDecmial to double coercion because without knowing type information beforehand, we buffer the most specific/accurate type. Whether the value is a BigDecimal or double may depend on the type-info type field. |
On buffering: buffer should ideally represent EXACT input that was received, wrt type, without changes: so if integral number exposed as As I said, I'll have so see what is going on: polymorphic handling is tricky, and |
I've created a somewhat alternative proposal #2982 which illustrates the problem on the TokenBuffer side. I think the numertype description of floating point values is problematic, as loss of precision is generally expected because we humans (and json) use base-ten decimal representation, where the computer internally does not. |
8ebe80b
to
b47997b
Compare
Thanks for the other PR. As I mentioned in the notes, I don't think that change is something I'd want to do -- ideally On plus side at least I understand better the role of buffering wrt. need to accept |
src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java
Outdated
Show resolved
Hide resolved
Thanks :-) It might be interesting to validate how buffering BigDecimal values rather than the input impacts memory overhead, for example JSON |
Ah. You had removed the |
The addition of Big numeric types, BigInteger and BigDecimal, prevents some tokens from being handled by existing `double` deserializers. This path occurs when data is buffered into a TokenBuffer while deserializing polymorphic types if the type name is not the first field received.
b47997b
to
dd30aa0
Compare
I've updated the conversion method name based on your suggestion. |
ah. Thanks! |
Right. My main concern really is that of correctness and consistency, but here's what I am thinking of implementation... will have to wait until 2.13 at least but:
For (3), may need to extract parsing code so that |
double
JsonCreators in jackson 2.12double
JsonCreators in jackson 2.12.0
The addition of Big numeric types, BigInteger and BigDecimal,
prevents some tokens from being handled by existing
double
deserializers.
This path occurs when data is buffered into a TokenBuffer while
deserializing polymorphic types if the type name is not the first
field received. It's possible that we can add data to the TokenBuffer
as
double
rather thanBigDecimal
to reduce memory overhead,however that's always going to be tricky due to how floating point
works. The opt-in flag to represent all decimal numbers as
BigDecimal would still break this case, so we may want to implement
both.