diff --git a/release-notes/CREDITS b/release-notes/CREDITS index 373df484ee..d69ec2c2d9 100644 --- a/release-notes/CREDITS +++ b/release-notes/CREDITS @@ -478,3 +478,7 @@ Maarten Billemont (lhunath@github) * Suggested #1184: Allow overriding of `transient` with explicit inclusion with `@JsonProperty` (2.8.0) +Vladimir Kulev (lightoze@github) + * Reported #1028: Ignore USE_BIG_DECIMAL_FOR_FLOATS for NaN/Infinity + (2.8.0) + diff --git a/release-notes/VERSION b/release-notes/VERSION index bf86dac793..c7058f877a 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -17,6 +17,8 @@ Project: jackson-databind (contributed by mkokho@github) #1017: Add new mapping exception type ('InvalidTypeIdException') for subtype resolution errors (suggested by natnan@github) +#1028: Ignore USE_BIG_DECIMAL_FOR_FLOATS for NaN/Infinity + (reported by Vladimir K, lightoze@github) #1082: Can not use static Creator factory methods for `Enum`s, with JsonCreator.Mode.PROPERTIES (contributed by Lokesh K) #1084: Change `TypeDeserializerBase` to take `JavaType` for `defaultImpl`, NOT `Class` diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java index f31703cb7b..ffcc6579dd 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.databind.deser.std; import java.io.IOException; +import java.math.BigDecimal; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; @@ -364,10 +365,18 @@ protected final JsonNode _fromFloat(JsonParser p, DeserializationContext ctxt, final JsonNodeFactory nodeFactory) throws IOException { JsonParser.NumberType nt = p.getNumberType(); - if (nt == JsonParser.NumberType.BIG_DECIMAL - || ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { + if (nt == JsonParser.NumberType.BIG_DECIMAL) { return nodeFactory.numberNode(p.getDecimalValue()); } + if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) { + // 20-May-2016, tatu: As per [databind#1028], need to be careful + // (note: JDK 1.8 would have `Double.isFinite()`) + double d = p.getDoubleValue(); + if (Double.isInfinite(d) || Double.isNaN(d)) { + return nodeFactory.numberNode(d); + } + return nodeFactory.numberNode(BigDecimal.valueOf(d)); + } return nodeFactory.numberNode(p.getDoubleValue()); } diff --git a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java index 6925a793f6..9376d776c2 100644 --- a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java @@ -52,6 +52,13 @@ protected static class LongWrapper { public LongWrapper() { } public LongWrapper(long value) { l = value; } } + + protected static class DoubleWrapper { + public double d; + + public DoubleWrapper() { } + public DoubleWrapper(double value) { d = value; } + } /** * Simple wrapper around String type, usually to test value diff --git a/src/test/java/com/fasterxml/jackson/databind/node/NotANumberConversionTest.java b/src/test/java/com/fasterxml/jackson/databind/node/NotANumberConversionTest.java new file mode 100644 index 0000000000..54a46369a7 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/node/NotANumberConversionTest.java @@ -0,0 +1,27 @@ +package com.fasterxml.jackson.databind.node; + +import com.fasterxml.jackson.databind.*; + +public class NotANumberConversionTest extends BaseMapTest +{ + public void testBigDecimalWithNaN() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS); + + JsonNode tree = m.valueToTree(new DoubleWrapper(Double.NaN)); + assertNotNull(tree); + String json = m.writeValueAsString(tree); + assertNotNull(json); + + tree = m.valueToTree(new DoubleWrapper(Double.NEGATIVE_INFINITY)); + assertNotNull(tree); + json = m.writeValueAsString(tree); + assertNotNull(json); + + tree = m.valueToTree(new DoubleWrapper(Double.POSITIVE_INFINITY)); + assertNotNull(tree); + json = m.writeValueAsString(tree); + assertNotNull(json); + } +}