From db61bb07f04512b6fc21a5ce4d2b7cd380a1e7fc Mon Sep 17 00:00:00 2001 From: Maicol Date: Fri, 9 Feb 2024 17:38:42 +0100 Subject: [PATCH] Adds support to `BigDecimal` in `JsonPrimitive#equals` (#2364) * Adds support to `BigDecimal` Adds to the JsonPrimitive#equals the possibility to support BigDecimal * Adds test Adds test to check if the equals work with BigDecimals. Code snippet from issue #904 * Implements review comments Replaces the `.equals` method with the `compareTo` in the `JsonPrimitive#equals` Change the ternary operator from `||` to `&&` so we are sure that both are `BigDecimal` Implements tests * Changes to follow the google-style-guide * implements review comment Co-authored-by: Marcono1234 * Fixes the `OperatorPrecedence` warn * Implements code improvements - Extracts `thisAsDouble` & `otherAsDouble` variables to avoid double functions calls. - Adds a comment to improve the code readability. * Implements `BigDecimal` check in the `JsonPrimitive.equals()` * Formats the code with `spotless:apply` --------- Co-authored-by: Marcono1234 --- .../java/com/google/gson/JsonPrimitive.java | 15 ++++++--- .../com/google/gson/JsonPrimitiveTest.java | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) 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(); + } }