diff --git a/gson/src/main/java/com/google/gson/JsonPrimitive.java b/gson/src/main/java/com/google/gson/JsonPrimitive.java index 2985ce98..2bce4be4 100644 --- a/gson/src/main/java/com/google/gson/JsonPrimitive.java +++ b/gson/src/main/java/com/google/gson/JsonPrimitive.java @@ -293,11 +293,16 @@ public final class JsonPrimitive extends JsonElement { : this.getAsNumber().longValue() == other.getAsNumber().longValue(); } if (value instanceof Number && other.value instanceof Number) { - double a = getAsNumber().doubleValue(); - // Java standard types other than double return true for two NaN. So, need - // special handling for double. - double b = other.getAsNumber().doubleValue(); - return a == b || (Double.isNaN(a) && Double.isNaN(b)); + if (value instanceof BigDecimal && other.value instanceof BigDecimal) { + // Uses compareTo to ignore scale of values, e.g. `0` and `0.00` should be considered equal + return this.getAsBigDecimal().compareTo(other.getAsBigDecimal()) == 0; + } + + double thisAsDouble = this.getAsDouble(); + double otherAsDouble = other.getAsDouble(); + // Don't use Double.compare(double, double) because that considers -0.0 and +0.0 not equal + return (thisAsDouble == otherAsDouble) + || (Double.isNaN(thisAsDouble) && Double.isNaN(otherAsDouble)); } return value.equals(other.value); } diff --git a/gson/src/test/java/com/google/gson/JsonPrimitiveTest.java b/gson/src/test/java/com/google/gson/JsonPrimitiveTest.java index 36a5da44..c816ff36 100644 --- a/gson/src/test/java/com/google/gson/JsonPrimitiveTest.java +++ b/gson/src/test/java/com/google/gson/JsonPrimitiveTest.java @@ -321,4 +321,35 @@ public class JsonPrimitiveTest { JsonPrimitive a = new JsonPrimitive("a"); assertThat(a).isSameInstanceAs(a.deepCopy()); // Primitives are immutable! } + + @Test + public void testBigDecimalEquals() { + JsonPrimitive small = new JsonPrimitive(1.0); + JsonPrimitive large = new JsonPrimitive(2.0); + assertThat(small.equals(large)).isFalse(); + + BigDecimal doubleMax = BigDecimal.valueOf(Double.MAX_VALUE); + JsonPrimitive smallBD = new JsonPrimitive(doubleMax.add(new BigDecimal("100.0"))); + JsonPrimitive largeBD = new JsonPrimitive(doubleMax.add(new BigDecimal("200.0"))); + assertThat(smallBD.equals(largeBD)).isFalse(); + } + + @Test + public void testBigDecimalEqualsZero() { + assertThat( + new JsonPrimitive(new BigDecimal("0.0")) + .equals(new JsonPrimitive(new BigDecimal("0.00")))) + .isTrue(); + + assertThat( + new JsonPrimitive(new BigDecimal("0.00")) + .equals(new JsonPrimitive(Double.valueOf("0.00")))) + .isTrue(); + } + + @Test + public void testEqualsDoubleNaNAndBigDecimal() { + assertThat(new JsonPrimitive(Double.NaN).equals(new JsonPrimitive(new BigDecimal("1.0")))) + .isFalse(); + } }