Skip to content
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

Improve JsonNode.DeepEquals numeric equality. #104255

Merged
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
Expand Down Expand Up @@ -1241,8 +1242,17 @@ internal static bool DeepEquals(JsonElement left, JsonElement right)
return true;

case JsonValueKind.Number:
// JSON numbers are equal if their raw representations are equal.
return left.GetRawValue().Span.SequenceEqual(right.GetRawValue().Span);
ReadOnlySpan<byte> leftRawValue = left.GetRawValue().Span;
ReadOnlySpan<byte> rightRawValue = right.GetRawValue().Span;

int bytesConsumed;
if (Utf8Parser.TryParse(leftRawValue, out decimal leftNumber, out bytesConsumed) && bytesConsumed == leftRawValue.Length &&
Utf8Parser.TryParse(rightRawValue, out decimal rightNumber, out bytesConsumed) && bytesConsumed == rightRawValue.Length)
{
return leftNumber == rightNumber;
}

return leftRawValue.SequenceEqual(rightRawValue);
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved

case JsonValueKind.String:
if (right.ValueIsEscaped)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,20 @@ public static void DeepEqualsPrimitiveType()
JsonNodeTests.AssertNotDeepEqual(JsonValue.Create(10), JsonValue.Create("10"));
}

[Theory]
[InlineData("1", "1.0", true)]
[InlineData("-0.0", "0", true)]
[InlineData("-1.1e3", "-1100", true)]
[InlineData("79228162514264337593543950336", "792281625142643375935439503360e-1", false)] // Not equal since it exceeds decimal.MaxValue
[InlineData("1.75e+300", "1.75E+300", false)] // Not equal due to case difference in exponent
public static void DeepEqualsNumericType(string leftStr, string rightStr, bool areEqual)
{
JsonNode left = JsonNode.Parse(leftStr);
JsonNode right = JsonNode.Parse(rightStr);

Assert.Equal(areEqual, JsonNode.DeepEquals(left, right));
}

[Fact]
public static void DeepEqualsJsonElement()
{
Expand Down