-
Notifications
You must be signed in to change notification settings - Fork 122
code to handle FasterXML/jackson-databind/issues/2141 #84
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
|
||
package com.fasterxml.jackson.datatype.jsr310.deser; | ||
|
||
import com.fasterxml.jackson.core.JsonParseException; | ||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.core.JsonToken; | ||
import com.fasterxml.jackson.core.JsonTokenId; | ||
|
@@ -40,6 +41,11 @@ public class DurationDeserializer extends JSR310DeserializerBase<Duration> | |
|
||
public static final DurationDeserializer INSTANCE = new DurationDeserializer(); | ||
|
||
private static final BigDecimal INSTANT_MAX = new BigDecimal( | ||
java.time.Instant.MAX.getEpochSecond() + "." + java.time.Instant.MAX.getNano()); | ||
private static final BigDecimal INSTANT_MIN = new BigDecimal( | ||
java.time.Instant.MIN.getEpochSecond() + "." + java.time.Instant.MIN.getNano()); | ||
|
||
private DurationDeserializer() | ||
{ | ||
super(Duration.class); | ||
|
@@ -52,6 +58,13 @@ public Duration deserialize(JsonParser parser, DeserializationContext context) t | |
{ | ||
case JsonTokenId.ID_NUMBER_FLOAT: | ||
BigDecimal value = parser.getDecimalValue(); | ||
// If the decimal isnt within the bounds of a float, bail out | ||
if(value.compareTo(INSTANT_MAX) > 0 || | ||
value.compareTo(INSTANT_MIN) < 0) { | ||
throw new JsonParseException(context.getParser(), | ||
"Value of Float too large to be converted to Duration"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turns out this isn't the correct boundary: For larger values, Jackson currently has the troubling behavior of
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For reference on behavior of similar overflow,
while
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Swapped for the following check, although I am not 100% sure about the correct min value:
All the test cases, including yours above now throw |
||
} | ||
|
||
long seconds = value.longValue(); | ||
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds); | ||
return Duration.ofSeconds(seconds, nanoseconds); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
package com.fasterxml.jackson.datatype.jsr310.deser; | ||
|
||
import com.fasterxml.jackson.annotation.JsonFormat; | ||
import com.fasterxml.jackson.core.JsonParseException; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this still needed? I think all three added imports are leftover from a prior revision. |
||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.core.JsonToken; | ||
import com.fasterxml.jackson.core.JsonTokenId; | ||
|
@@ -29,6 +30,8 @@ | |
|
||
import java.io.IOException; | ||
import java.math.BigDecimal; | ||
import java.text.DecimalFormat; | ||
import java.text.NumberFormat; | ||
import java.time.DateTimeException; | ||
import java.time.Instant; | ||
import java.time.OffsetDateTime; | ||
|
@@ -52,6 +55,11 @@ public class InstantDeserializer<T extends Temporal> | |
{ | ||
private static final long serialVersionUID = 1L; | ||
|
||
private static final BigDecimal INSTANT_MAX = new BigDecimal( | ||
java.time.Instant.MAX.getEpochSecond() + "." + java.time.Instant.MAX.getNano()); | ||
private static final BigDecimal INSTANT_MIN = new BigDecimal( | ||
java.time.Instant.MIN.getEpochSecond() + "." + java.time.Instant.MIN.getNano()); | ||
|
||
/** | ||
* Constants used to check if the time offset is zero. See [jackson-modules-java8#18] | ||
* | ||
|
@@ -277,8 +285,15 @@ protected T _fromLong(DeserializationContext context, long timestamp) | |
timestamp, this.getZone(context))); | ||
} | ||
|
||
protected T _fromDecimal(DeserializationContext context, BigDecimal value) | ||
protected T _fromDecimal(DeserializationContext context, BigDecimal value) throws JsonParseException | ||
{ | ||
// If the decimal isnt within the bounds of an Instant, bail out | ||
if(value.compareTo(INSTANT_MAX) > 0 || | ||
value.compareTo(INSTANT_MIN) < 0) { | ||
throw new JsonParseException(context.getParser(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Today, this method throws This test case:
results in:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I swapped the checks to throw I updated the bounds for duration to be the following, although I am not 100% certain it is correct with regards to minimum:
|
||
"Value of String too large to be converted to Instant"); | ||
} | ||
|
||
long seconds = value.longValue(); | ||
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds); | ||
return fromNanoseconds.apply(new FromDecimalArguments( | ||
|
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.
Shouldn't "float" be "Instant"? Also, misspelling of "isn't".
Also might be worth pointing out in comment thatUPDATE: they do not.Duration
andInstant
share the same range.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.
Changed to
// If the decimal isn't within the bounds of a duration, bail out
since a duration has different bounds than an instant.