Repository: google/gson
Issue: BigDecimal equals problem

Dear developers, it looks like the primitive's equals to did not handle BigDecimal's comparison. The following test will fail:

```
  public void testUnequalDecimals() {
      JsonPrimitive small = new JsonPrimitive(1.0);
      JsonPrimitive large = new JsonPrimitive(2.0);
      assertFalse("small = large", small.equals(large));

      BigDecimal dmax = BigDecimal.valueOf(Double.MAX_VALUE);
      JsonPrimitive smallBD =        // dmax + 100.0
          new JsonPrimitive(dmax.add(new BigDecimal("100.0")));
      JsonPrimitive largeBD =        // dmax + 200.0
          new JsonPrimitive(dmax.add(new BigDecimal("200.0")));
      assertFalse("small = large", smallBD.equals(largeBD));
  }
```

Could you consider a fix for this, so it can support big decimal comparisons, too?

Thanks!


Changed files:
gson/src/test/java/com/google/gson/JsonPrimitiveTest.java
gson/src/main/java/com/google/gson/JsonPrimitive.java

diff --git a/gson/src/main/java/com/google/gson/JsonPrimitive.java b/gson/src/main/java/com/google/gson/JsonPrimitive.java
index 827de959..f143da97 100644
--- a/gson/src/main/java/com/google/gson/JsonPrimitive.java
+++ b/gson/src/main/java/com/google/gson/JsonPrimitive.java
@@ -290,11 +290,10 @@ 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));
+      return this.value instanceof BigDecimal && other.value instanceof BigDecimal
+          ? this.getAsBigDecimal().compareTo(other.getAsBigDecimal()) == 0
+          : this.getAsDouble() == other.getAsDouble()
+              || (Double.isNaN(this.getAsDouble()) && Double.isNaN(other.getAsDouble()));
     }
     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 24947012..959313ad 100644
--- a/gson/src/test/java/com/google/gson/JsonPrimitiveTest.java
+++ b/gson/src/test/java/com/google/gson/JsonPrimitiveTest.java
@@ -316,4 +316,31 @@ 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();
+  }
 }