From e8ea42199d9646b08b1365f780e6778276b3a53f Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sat, 20 Jan 2024 14:35:25 +1300 Subject: [PATCH 1/8] Bump .NET version and remove deprecated versions Co-authored-by: Martin Tracey <1207505+matracey@users.noreply.github.com> --- .github/workflows/build-and-test.yaml | 6 +++--- src/Directory.Build.props | 6 +++--- .../SystemTextJson.JsonDiffPatch.csproj | 4 ++-- test/Directory.Build.props | 4 ++++ .../SystemTextJson.JsonDiffPatch.Benchmark.csproj | 5 ++--- .../SystemTextJson.JsonDiffPatch.MSTest.Tests.csproj | 12 ++++-------- .../SystemTextJson.JsonDiffPatch.NUnit.Tests.csproj | 12 ++++-------- .../SystemTextJson.JsonDiffPatch.UnitTests.csproj | 10 +++------- .../SystemTextJson.JsonDiffPatch.Xunit.Tests.csproj | 10 +++------- 9 files changed, 28 insertions(+), 41 deletions(-) diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index 9f8f20b..0edd1ac 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -11,7 +11,7 @@ jobs: strategy: matrix: build-configuration: [ Debug, Release ] - test-target-framework: [ net6.0, net5.0, netcoreapp3.1 ] + test-target-framework: [ net8.0, net7.0, net6.0 ] name: Build And Test (${{ matrix.test-target-framework }}, ${{ matrix.build-configuration }}) runs-on: ubuntu-latest steps: @@ -20,9 +20,9 @@ jobs: uses: actions/setup-dotnet@v2 with: dotnet-version: | + 8.x + 7.x 6.x - 5.x - 3.1.x - name: Restore run: dotnet restore ${{ env.JsonDiffPatchSolutionPath }} - name: Build diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a58122d..4887eea 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ <Project> <PropertyGroup> - <TargetFrameworks>netstandard2.0;netstandard2.1;net461</TargetFrameworks> + <TargetFrameworks>net8.0;net7.0;net6.0;netstandard2.0;net462</TargetFrameworks> <Nullable>enable</Nullable> <LangVersion>latest</LangVersion> <GenerateDocumentationFile>true</GenerateDocumentationFile> @@ -9,10 +9,10 @@ </PropertyGroup> <PropertyGroup> - <JsonDiffPatchPackageVersion>1.3.1</JsonDiffPatchPackageVersion> + <JsonDiffPatchPackageVersion>2.0.0</JsonDiffPatchPackageVersion> <Authors>Wei Chen</Authors> <PackageProjectUrl>https://github.com/weichch/system-text-json-jsondiffpatch</PackageProjectUrl> - <Copyright>Copyright © Wei Chen 2022</Copyright> + <Copyright>Copyright © Wei Chen 2024</Copyright> <PackageIcon>icon.png</PackageIcon> <PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageReleaseNotes>https://github.com/weichch/system-text-json-jsondiffpatch/blob/$(JsonDiffPatchPackageVersion)/ReleaseNotes.md</PackageReleaseNotes> diff --git a/src/SystemTextJson.JsonDiffPatch/SystemTextJson.JsonDiffPatch.csproj b/src/SystemTextJson.JsonDiffPatch/SystemTextJson.JsonDiffPatch.csproj index 4bb32a1..a92ba95 100644 --- a/src/SystemTextJson.JsonDiffPatch/SystemTextJson.JsonDiffPatch.csproj +++ b/src/SystemTextJson.JsonDiffPatch/SystemTextJson.JsonDiffPatch.csproj @@ -11,11 +11,11 @@ </PropertyGroup> <ItemGroup> - <Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461'" /> + <Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net462'" /> </ItemGroup> <ItemGroup> - <PackageReference Include="System.Text.Json" Version="6.0.0" /> + <PackageReference Include="System.Text.Json" Version="8.0.0" /> </ItemGroup> <ItemGroup> diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 41d357d..6c40006 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,5 +1,9 @@ <Project> + <PropertyGroup> + <TargetFrameworks>net8.0;net7.0;net6.0;net48</TargetFrameworks> + </PropertyGroup> + <PropertyGroup> <IsPackable>false</IsPackable> <Nullable>enable</Nullable> diff --git a/test/SystemTextJson.JsonDiffPatch.Benchmark/SystemTextJson.JsonDiffPatch.Benchmark.csproj b/test/SystemTextJson.JsonDiffPatch.Benchmark/SystemTextJson.JsonDiffPatch.Benchmark.csproj index 3f3c722..c13337c 100644 --- a/test/SystemTextJson.JsonDiffPatch.Benchmark/SystemTextJson.JsonDiffPatch.Benchmark.csproj +++ b/test/SystemTextJson.JsonDiffPatch.Benchmark/SystemTextJson.JsonDiffPatch.Benchmark.csproj @@ -2,14 +2,13 @@ <PropertyGroup> <OutputType>Exe</OutputType> - <TargetFrameworks>net6.0;net48</TargetFrameworks> <ServerGarbageCollection>true</ServerGarbageCollection> </PropertyGroup> <ItemGroup> - <PackageReference Include="BenchmarkDotNet" Version="0.13.1" /> + <PackageReference Include="BenchmarkDotNet" Version="0.13.12" /> <PackageReference Include="JsonDiffPatch.Net" Version="2.3.0" /> - <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> </ItemGroup> <ItemGroup> diff --git a/test/SystemTextJson.JsonDiffPatch.MSTest.Tests/SystemTextJson.JsonDiffPatch.MSTest.Tests.csproj b/test/SystemTextJson.JsonDiffPatch.MSTest.Tests/SystemTextJson.JsonDiffPatch.MSTest.Tests.csproj index 7db3076..644d848 100644 --- a/test/SystemTextJson.JsonDiffPatch.MSTest.Tests/SystemTextJson.JsonDiffPatch.MSTest.Tests.csproj +++ b/test/SystemTextJson.JsonDiffPatch.MSTest.Tests/SystemTextJson.JsonDiffPatch.MSTest.Tests.csproj @@ -1,14 +1,10 @@ <Project Sdk="Microsoft.NET.Sdk"> - <PropertyGroup> - <TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net461;net48</TargetFrameworks> - </PropertyGroup> - <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" /> - <PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> - <PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> - <PackageReference Include="coverlet.collector" Version="3.0.2"> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> + <PackageReference Include="MSTest.TestAdapter" Version="3.1.1" /> + <PackageReference Include="MSTest.TestFramework" Version="3.1.1" /> + <PackageReference Include="coverlet.collector" Version="6.0.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> diff --git a/test/SystemTextJson.JsonDiffPatch.NUnit.Tests/SystemTextJson.JsonDiffPatch.NUnit.Tests.csproj b/test/SystemTextJson.JsonDiffPatch.NUnit.Tests/SystemTextJson.JsonDiffPatch.NUnit.Tests.csproj index 63a5b31..8e84012 100644 --- a/test/SystemTextJson.JsonDiffPatch.NUnit.Tests/SystemTextJson.JsonDiffPatch.NUnit.Tests.csproj +++ b/test/SystemTextJson.JsonDiffPatch.NUnit.Tests/SystemTextJson.JsonDiffPatch.NUnit.Tests.csproj @@ -1,14 +1,10 @@ <Project Sdk="Microsoft.NET.Sdk"> - <PropertyGroup> - <TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net461;net48</TargetFrameworks> - </PropertyGroup> - <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" /> - <PackageReference Include="NUnit" Version="3.13.2"/> - <PackageReference Include="NUnit3TestAdapter" Version="4.0.0"/> - <PackageReference Include="coverlet.collector" Version="3.0.2"> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> + <PackageReference Include="NUnit" Version="3.14.0"/> + <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> + <PackageReference Include="coverlet.collector" Version="6.0.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> diff --git a/test/SystemTextJson.JsonDiffPatch.UnitTests/SystemTextJson.JsonDiffPatch.UnitTests.csproj b/test/SystemTextJson.JsonDiffPatch.UnitTests/SystemTextJson.JsonDiffPatch.UnitTests.csproj index 3a9b75e..729edcd 100644 --- a/test/SystemTextJson.JsonDiffPatch.UnitTests/SystemTextJson.JsonDiffPatch.UnitTests.csproj +++ b/test/SystemTextJson.JsonDiffPatch.UnitTests/SystemTextJson.JsonDiffPatch.UnitTests.csproj @@ -1,17 +1,13 @@ <Project Sdk="Microsoft.NET.Sdk"> - <PropertyGroup> - <TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net461;net48</TargetFrameworks> - </PropertyGroup> - <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PackageReference Include="xunit" Version="2.4.1" /> - <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> + <PackageReference Include="xunit.runner.visualstudio" Version="2.5.6"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> - <PackageReference Include="coverlet.collector" Version="3.0.2"> + <PackageReference Include="coverlet.collector" Version="6.0.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> diff --git a/test/SystemTextJson.JsonDiffPatch.Xunit.Tests/SystemTextJson.JsonDiffPatch.Xunit.Tests.csproj b/test/SystemTextJson.JsonDiffPatch.Xunit.Tests/SystemTextJson.JsonDiffPatch.Xunit.Tests.csproj index 54b9427..08aef5c 100644 --- a/test/SystemTextJson.JsonDiffPatch.Xunit.Tests/SystemTextJson.JsonDiffPatch.Xunit.Tests.csproj +++ b/test/SystemTextJson.JsonDiffPatch.Xunit.Tests/SystemTextJson.JsonDiffPatch.Xunit.Tests.csproj @@ -1,17 +1,13 @@ <Project Sdk="Microsoft.NET.Sdk"> - <PropertyGroup> - <TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net461;net48</TargetFrameworks> - </PropertyGroup> - <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PackageReference Include="xunit" Version="2.4.1" /> - <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> + <PackageReference Include="xunit.runner.visualstudio" Version="2.5.6"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> - <PackageReference Include="coverlet.collector" Version="3.0.2"> + <PackageReference Include="coverlet.collector" Version="6.0.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> From 67e28bb47052ad8ca3dc4ec64af1c3aecf3ae40a Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sat, 20 Jan 2024 14:36:43 +1300 Subject: [PATCH 2/8] Support built-in DeepEquals and DeepClone --- src/Directory.Build.props | 4 +++ .../Diffs/JsonDiffDelta.cs | 8 +++--- .../JsonDiffPatcher.Clone.cs | 10 ++++++- .../JsonDiffPatcher.DeepEquals.cs | 4 +++ .../Patching/JsonDiffPatcher.Patch.cs | 4 +-- .../DemoFileTests.cs | 12 ++++---- .../NodeTests/ElementDeepEqualsTests.cs | 28 +++++++++---------- .../NodeTests/ObjectDeepEqualsTests.cs | 24 ++++++++-------- 8 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 4887eea..80b3025 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -24,6 +24,10 @@ <FileVersion>1.0.0.0</FileVersion> </PropertyGroup> + <PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'"> + <DefineConstants>$(DefineConstants);HAVE_NEW_JSONNODE_METHODS</DefineConstants> + </PropertyGroup> + <ItemGroup> <None Include="..\..\icon.png" Link="Packaging\icon.png" Pack="true" PackagePath="\" /> <None Include="..\..\LICENSE" Link="Packaging\LICENSE" Pack="true" PackagePath="\" /> diff --git a/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs b/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs index 5300504..83df1d4 100644 --- a/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs +++ b/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs @@ -244,22 +244,22 @@ public void Added(JsonNode? newValue) { EnsureDeltaType(nameof(Added), count: 1); var arr = Document!.AsArray(); - arr[0] = newValue.DeepClone(); + arr[0] = JsonDiffPatcher.DeepClone(newValue); } public void Modified(JsonNode? oldValue, JsonNode? newValue) { EnsureDeltaType(nameof(Modified), count: 2); var arr = Document!.AsArray(); - arr[0] = oldValue.DeepClone(); - arr[1] = newValue.DeepClone(); + arr[0] = JsonDiffPatcher.DeepClone(oldValue); + arr[1] = JsonDiffPatcher.DeepClone(newValue); } public void Deleted(JsonNode? oldValue) { EnsureDeltaType(nameof(Deleted), count: 3, opType: OpTypeDeleted); var arr = Document!.AsArray(); - arr[0] = oldValue.DeepClone(); + arr[0] = JsonDiffPatcher.DeepClone(oldValue); arr[1] = 0; } diff --git a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs b/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs index 8296cca..ff7613e 100644 --- a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs +++ b/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs @@ -10,8 +10,15 @@ static partial class JsonDiffPatcher /// Creates a deep copy of the <see cref="JsonNode"/>. /// </summary> /// <param name="obj">The <see cref="JsonNode"/>.</param> +#if HAVE_NEW_JSONNODE_METHODS + public static T? DeepClone<T>(T? obj) where T : JsonNode +#else public static T? DeepClone<T>(this T? obj) where T : JsonNode +#endif { +#if HAVE_NEW_JSONNODE_METHODS + return obj is null ? null : (T)obj.DeepClone(); +#else return (T?)(obj switch { null => (JsonNode?)null, @@ -26,9 +33,10 @@ static partial class JsonDiffPatcher { foreach (var kvp in obj) { - yield return new KeyValuePair<string, JsonNode?>(kvp.Key, kvp.Value.DeepClone()); + yield return new KeyValuePair<string, JsonNode?>(kvp.Key, DeepClone(kvp.Value)); } } +#endif } private static JsonValue? CloneJsonValue(JsonValue? value) diff --git a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs b/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs index 89f64e8..9964815 100644 --- a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs +++ b/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs @@ -13,7 +13,11 @@ static partial class JsonDiffPatcher /// <param name="right">The right value.</param> public static bool DeepEquals(this JsonNode? left, JsonNode? right) { +#if HAVE_NEW_JSONNODE_METHODS + return JsonNode.DeepEquals(left, right); +#else return DeepEquals(left, right, default(JsonComparerOptions)); +#endif } /// <summary> diff --git a/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs b/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs index b51f1d3..f4e1c7b 100644 --- a/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs +++ b/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs @@ -52,7 +52,7 @@ when left is JsonValue jsonValue /// <param name="options">The patch options.</param> public static JsonNode? PatchNew(this JsonNode? left, JsonNode? patch, JsonPatchOptions options = default) { - var copy = left.DeepClone(); + var copy = DeepClone(left); Patch(ref copy, patch, options); return copy; } @@ -105,7 +105,7 @@ when right is JsonValue jsonValue /// <param name="options">The patch options.</param> public static JsonNode? ReversePatchNew(this JsonNode? right, JsonNode? patch, JsonReversePatchOptions options = default) { - var copy = right.DeepClone(); + var copy = DeepClone(right); ReversePatch(ref copy, patch, options); return copy; } diff --git a/test/SystemTextJson.JsonDiffPatch.UnitTests/DemoFileTests.cs b/test/SystemTextJson.JsonDiffPatch.UnitTests/DemoFileTests.cs index 57fbf99..343b142 100644 --- a/test/SystemTextJson.JsonDiffPatch.UnitTests/DemoFileTests.cs +++ b/test/SystemTextJson.JsonDiffPatch.UnitTests/DemoFileTests.cs @@ -74,10 +74,10 @@ public void Roundtrip_DemoFile() Assert.Null(left.Diff(originalLeft, diffOptions)); JsonDiffPatcher.Patch(ref left, diff); - Assert.True(left.DeepEquals(right)); + Assert.True(left.DeepEquals(right, default(JsonComparerOptions))); JsonDiffPatcher.ReversePatch(ref left, diff); - Assert.True(left.DeepEquals(originalLeft)); + Assert.True(left.DeepEquals(originalLeft, default(JsonComparerOptions))); } [Fact] @@ -89,7 +89,7 @@ public void Diff_DemoJson_JsonPatch() @"Examples/demo_right.json", new JsonPatchDeltaFormatter()); - Assert.True(expectedDiff.DeepEquals(diff)); + Assert.True(expectedDiff.DeepEquals(diff, default(JsonComparerOptions))); } [Fact] @@ -121,10 +121,10 @@ public void Roundtrip_LargeObjects() Assert.Null(left.Diff(originalLeft, diffOptions)); JsonDiffPatcher.Patch(ref left, diff); - Assert.True(left.DeepEquals(right)); + Assert.True(left.DeepEquals(right, default(JsonComparerOptions))); JsonDiffPatcher.ReversePatch(ref left, diff); - Assert.True(left.DeepEquals(originalLeft)); + Assert.True(left.DeepEquals(originalLeft, default(JsonComparerOptions))); } [Fact] @@ -136,7 +136,7 @@ public void Diff_LargeObjects_JsonPatch() @"Examples/large_right.json", new JsonPatchDeltaFormatter()); - Assert.True(expectedDiff.DeepEquals(diff)); + Assert.True(expectedDiff.DeepEquals(diff, default(JsonComparerOptions))); } } } diff --git a/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ElementDeepEqualsTests.cs b/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ElementDeepEqualsTests.cs index 95c60e9..44c96c7 100644 --- a/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ElementDeepEqualsTests.cs +++ b/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ElementDeepEqualsTests.cs @@ -12,7 +12,7 @@ public void Object_Identical() var json1 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"qux\"}"); var json2 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"qux\"}"); - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -21,7 +21,7 @@ public void Object_Whitespace() var json1 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"qux\"}"); var json2 = JsonNode.Parse("{ \"foo\": \"bar\", \"baz\":\"qux\" }"); - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -30,7 +30,7 @@ public void Object_PropertyOrdering() var json1 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"qux\"}"); var json2 = JsonNode.Parse("{\"baz\":\"qux\",\"foo\":\"bar\"}"); - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -39,7 +39,7 @@ public void Object_PropertyValue() var json1 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"qux\"}"); var json2 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"quz\"}"); - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -48,7 +48,7 @@ public void Object_MissingProperty() var json1 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"qux\"}"); var json2 = JsonNode.Parse("{\"foo\":\"bar\"}"); - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -57,7 +57,7 @@ public void Object_ExtraProperty() var json1 = JsonNode.Parse("{\"foo\":\"bar\"}"); var json2 = JsonNode.Parse("{\"foo\":\"bar\",\"baz\":\"qux\"}"); - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -66,7 +66,7 @@ public void Array_Identical() var json1 = JsonNode.Parse("[1,2,3]"); var json2 = JsonNode.Parse("[1,2,3]"); - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -75,7 +75,7 @@ public void Array_Whitespace() var json1 = JsonNode.Parse("[1,2,3]"); var json2 = JsonNode.Parse("[ 1, 2, 3 ]"); - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -84,7 +84,7 @@ public void Array_ItemOrdering() var json1 = JsonNode.Parse("[1,2,3]"); var json2 = JsonNode.Parse("[1,3,2]"); - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -93,7 +93,7 @@ public void Array_ItemValue() var json1 = JsonNode.Parse("[1,2,3]"); var json2 = JsonNode.Parse("[1,2,5]"); - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -102,7 +102,7 @@ public void Array_MissingItem() var json1 = JsonNode.Parse("[1,2,3]"); var json2 = JsonNode.Parse("[1,2]"); - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -111,14 +111,14 @@ public void Array_ExtraItem() var json1 = JsonNode.Parse("[1,2]"); var json2 = JsonNode.Parse("[1,2,3]"); - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Theory] [MemberData(nameof(NodeTestData.ElementRawTextEqual), MemberType = typeof(NodeTestData))] public void Value_RawText(JsonValue json1, JsonValue json2, bool expected) { - Assert.Equal(expected, json1.DeepEquals(json2)); + Assert.Equal(expected, json1.DeepEquals(json2, default(JsonComparerOptions))); } [Theory] @@ -132,7 +132,7 @@ public void Value_Semantic(JsonValue json1, JsonValue json2, bool expected) [MemberData(nameof(NodeTestData.ElementObjectSemanticEqual), MemberType = typeof(NodeTestData))] public void Value_ElementObjectSemanticEqual(JsonValue json1, JsonValue json2, bool expected) { - Assert.Equal(expected, json1.DeepEquals(json2)); + Assert.Equal(expected, json1.DeepEquals(json2, default(JsonComparerOptions))); } } } diff --git a/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ObjectDeepEqualsTests.cs b/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ObjectDeepEqualsTests.cs index 3278e1e..719d9e3 100644 --- a/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ObjectDeepEqualsTests.cs +++ b/test/SystemTextJson.JsonDiffPatch.UnitTests/NodeTests/ObjectDeepEqualsTests.cs @@ -9,7 +9,7 @@ public class ObjectDeepEqualsTests [Fact] public void Default() { - Assert.True(default(JsonNode).DeepEquals(default)); + Assert.True(default(JsonNode).DeepEquals(default, default(JsonComparerOptions))); } [Fact] @@ -26,7 +26,7 @@ public void Object_Identical() {"baz", "qux"} }; - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -43,7 +43,7 @@ public void Object_PropertyOrdering() {"foo", "bar"} }; - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -60,7 +60,7 @@ public void Object_PropertyValue() {"baz", "quz"} }; - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -76,7 +76,7 @@ public void Object_MissingProperty() {"foo", "bar"} }; - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -92,7 +92,7 @@ public void Object_ExtraProperty() {"baz", "qux"} }; - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -101,7 +101,7 @@ public void Array_Identical() var json1 = new JsonArray {1, 2, 3}; var json2 = new JsonArray {1, 2, 3}; - Assert.True(json1.DeepEquals(json2)); + Assert.True(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -110,7 +110,7 @@ public void Array_ItemOrdering() var json1 = new JsonArray {1, 2, 3}; var json2 = new JsonArray {1, 3, 2}; - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -119,7 +119,7 @@ public void Array_ItemValue() var json1 = new JsonArray {1, 2, 3}; var json2 = new JsonArray {1, 2, 5}; - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -128,7 +128,7 @@ public void Array_MissingItem() var json1 = new JsonArray {1, 2, 3}; var json2 = new JsonArray {1, 2}; - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Fact] @@ -137,14 +137,14 @@ public void Array_ExtraItem() var json1 = new JsonArray {1, 2}; var json2 = new JsonArray {1, 2, 3}; - Assert.False(json1.DeepEquals(json2)); + Assert.False(json1.DeepEquals(json2, default(JsonComparerOptions))); } [Theory] [MemberData(nameof(NodeTestData.ObjectSemanticEqual), MemberType = typeof(NodeTestData))] public void Value_ObjectSemanticEqual(JsonValue json1, JsonValue json2, bool expected) { - Assert.Equal(expected, json1.DeepEquals(json2)); + Assert.Equal(expected, json1.DeepEquals(json2, default(JsonComparerOptions))); } } } From d4f9a03e00487bcb6cf34a4636dba42916ed8bb4 Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sat, 20 Jan 2024 15:06:51 +1300 Subject: [PATCH 3/8] Fix tests --- .../JsonAssert.cs | 14 ++++++- .../JsonAssert.cs | 42 ++++++++++++------- .../JsonAssert.cs | 14 ++++++- .../JsonString.cs | 17 ++++++-- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/SystemTextJson.JsonDiffPatch.MSTest/JsonAssert.cs b/src/SystemTextJson.JsonDiffPatch.MSTest/JsonAssert.cs index f24b52d..9fd6663 100644 --- a/src/SystemTextJson.JsonDiffPatch.MSTest/JsonAssert.cs +++ b/src/SystemTextJson.JsonDiffPatch.MSTest/JsonAssert.cs @@ -1,4 +1,5 @@ using System.Text.Json.Nodes; +using System.Text.Json.Serialization.Metadata; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace System.Text.Json.JsonDiffPatch.MsTest @@ -8,7 +9,18 @@ namespace System.Text.Json.JsonDiffPatch.MsTest /// </summary> public static class JsonAssert { - private static readonly JsonSerializerOptions SerializerOptions = new() {WriteIndented = true}; + private static readonly JsonSerializerOptions SerializerOptions; + + static JsonAssert() + { + SerializerOptions = new() + { + TypeInfoResolver = new DefaultJsonTypeInfoResolver(), + WriteIndented = true + }; + + SerializerOptions.MakeReadOnly(); + } /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, diff --git a/src/SystemTextJson.JsonDiffPatch.NUnit/JsonAssert.cs b/src/SystemTextJson.JsonDiffPatch.NUnit/JsonAssert.cs index b1ff3a0..3534a1a 100644 --- a/src/SystemTextJson.JsonDiffPatch.NUnit/JsonAssert.cs +++ b/src/SystemTextJson.JsonDiffPatch.NUnit/JsonAssert.cs @@ -1,4 +1,5 @@ using System.Text.Json.Nodes; +using System.Text.Json.Serialization.Metadata; using NUnit.Framework; namespace System.Text.Json.JsonDiffPatch.Nunit @@ -8,7 +9,18 @@ namespace System.Text.Json.JsonDiffPatch.Nunit /// </summary> public static class JsonAssert { - private static readonly JsonSerializerOptions SerializerOptions = new() {WriteIndented = true}; + private static readonly JsonSerializerOptions SerializerOptions; + + static JsonAssert() + { + SerializerOptions = new() + { + TypeInfoResolver = new DefaultJsonTypeInfoResolver(), + WriteIndented = true + }; + + SerializerOptions.MakeReadOnly(); + } /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, @@ -179,7 +191,7 @@ public static void JsonAreEqual(this Assert assert, string? expected, string? ac /// <param name="output">Whether to print diff result.</param> public static void JsonAreEqual(this Assert assert, string? expected, string? actual, bool output) => AreEqual(expected, actual, output); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -191,7 +203,7 @@ public static void JsonAreEqual(this Assert assert, string? expected, string? ac public static void JsonAreEqual(this Assert assert, string? expected, string? actual, JsonDiffOptions diffOptions) => AreEqual(expected, actual, diffOptions); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -204,7 +216,7 @@ public static void JsonAreEqual(this Assert assert, string? expected, string? ac public static void JsonAreEqual(this Assert assert, string? expected, string? actual, JsonDiffOptions diffOptions, bool output) => AreEqual(expected, actual, diffOptions, output); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -230,7 +242,7 @@ public static void JsonAreEqual(this Assert assert, string? expected, string? ac JsonDiffOptions diffOptions, Func<JsonNode, string> outputFormatter) => AreEqual(expected, actual, diffOptions, outputFormatter); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -242,7 +254,7 @@ public static void JsonAreEqual(this Assert assert, string? expected, string? ac public static void JsonAreEqual<T>(this Assert assert, T? expected, T? actual) where T : JsonNode => AreEqual(expected, actual); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -255,7 +267,7 @@ public static void JsonAreEqual<T>(this Assert assert, T? expected, T? actual) public static void JsonAreEqual<T>(this Assert assert, T? expected, T? actual, bool output) where T : JsonNode => AreEqual(expected, actual, output); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -268,7 +280,7 @@ public static void JsonAreEqual<T>(this Assert assert, T? expected, T? actual, b public static void JsonAreEqual<T>(this Assert assert, T? expected, T? actual, JsonDiffOptions diffOptions) where T : JsonNode => AreEqual(expected, actual, diffOptions); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -283,7 +295,7 @@ public static void JsonAreEqual<T>(this Assert assert, T? expected, T? actual, JsonDiffOptions diffOptions, bool output) where T : JsonNode => AreEqual(expected, actual, diffOptions, output); - + /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -378,7 +390,7 @@ public static void AreNotEqual(string? expected, string? actual) public static void AreNotEqual(string? expected, string? actual, JsonDiffOptions diffOptions) => AreNotEqual(expected is null ? null : JsonNode.Parse(expected), actual is null ? null : JsonNode.Parse(actual), diffOptions); - + /// <summary> /// Tests whether two JSON objects are not equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -389,7 +401,7 @@ public static void AreNotEqual(string? expected, string? actual, JsonDiffOptions public static void AreNotEqual<T>(T? expected, T? actual) where T : JsonNode => HandleAreNotEqual(expected, actual, null); - + /// <summary> /// Tests whether two JSON objects are not equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -402,7 +414,7 @@ public static void AreNotEqual<T>(T? expected, T? actual, JsonDiffOptions diffOp where T : JsonNode => HandleAreNotEqual(expected, actual, diffOptions ?? throw new ArgumentNullException(nameof(diffOptions))); - + /// <summary> /// Tests whether two JSON objects are not equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -412,7 +424,7 @@ public static void AreNotEqual<T>(T? expected, T? actual, JsonDiffOptions diffOp /// <param name="actual">The actual value.</param> public static void JsonAreNotEqual(this Assert assert, string? expected, string? actual) => AreNotEqual(expected, actual); - + /// <summary> /// Tests whether two JSON objects are not equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -424,7 +436,7 @@ public static void JsonAreNotEqual(this Assert assert, string? expected, string? public static void JsonAreNotEqual(this Assert assert, string? expected, string? actual, JsonDiffOptions diffOptions) => AreNotEqual(expected, actual, diffOptions); - + /// <summary> /// Tests whether two JSON objects are not equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. @@ -436,7 +448,7 @@ public static void JsonAreNotEqual(this Assert assert, string? expected, string? public static void JsonAreNotEqual<T>(this Assert assert, T? expected, T? actual) where T : JsonNode => AreNotEqual(expected, actual); - + /// <summary> /// Tests whether two JSON objects are not equal. Note that when comparing the specified objects, /// the ordering of members in the objects is not significant. diff --git a/src/SystemTextJson.JsonDiffPatch.Xunit/JsonAssert.cs b/src/SystemTextJson.JsonDiffPatch.Xunit/JsonAssert.cs index fcc56d5..81b5ee4 100644 --- a/src/SystemTextJson.JsonDiffPatch.Xunit/JsonAssert.cs +++ b/src/SystemTextJson.JsonDiffPatch.Xunit/JsonAssert.cs @@ -1,4 +1,5 @@ using System.Text.Json.Nodes; +using System.Text.Json.Serialization.Metadata; namespace System.Text.Json.JsonDiffPatch.Xunit { @@ -7,7 +8,18 @@ namespace System.Text.Json.JsonDiffPatch.Xunit /// </summary> public static class JsonAssert { - private static readonly JsonSerializerOptions SerializerOptions = new() {WriteIndented = true}; + private static readonly JsonSerializerOptions SerializerOptions; + + static JsonAssert() + { + SerializerOptions = new() + { + TypeInfoResolver = new DefaultJsonTypeInfoResolver(), + WriteIndented = true + }; + + SerializerOptions.MakeReadOnly(); + } /// <summary> /// Tests whether two JSON objects are equal. Note that when comparing the specified objects, diff --git a/src/SystemTextJson.JsonDiffPatch/JsonString.cs b/src/SystemTextJson.JsonDiffPatch/JsonString.cs index dcf540d..da5a0de 100644 --- a/src/SystemTextJson.JsonDiffPatch/JsonString.cs +++ b/src/SystemTextJson.JsonDiffPatch/JsonString.cs @@ -2,15 +2,26 @@ using System.Runtime.CompilerServices; using System.Text.Encodings.Web; using System.Text.Json.Nodes; +using System.Text.Json.Serialization.Metadata; namespace System.Text.Json.JsonDiffPatch { internal struct JsonString { - internal static readonly JsonSerializerOptions SerializerOptions = new() + internal static readonly JsonSerializerOptions SerializerOption; + + private static readonly JsonSerializerOptions SerializerOptions; + + static JsonString() { - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping - }; + SerializerOptions = new() + { + TypeInfoResolver = new DefaultJsonTypeInfoResolver(), + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + + SerializerOptions.MakeReadOnly(); + } private DateTime? _dateTimeValue; private DateTimeOffset? _dateTimeOffsetValue; From fc5c4e0c99f77221a8fbdba79bb97d1d247e9d35 Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sat, 20 Jan 2024 15:12:34 +1300 Subject: [PATCH 4/8] Fix warnings --- src/SystemTextJson.JsonDiffPatch/JsonString.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/SystemTextJson.JsonDiffPatch/JsonString.cs b/src/SystemTextJson.JsonDiffPatch/JsonString.cs index da5a0de..8efade0 100644 --- a/src/SystemTextJson.JsonDiffPatch/JsonString.cs +++ b/src/SystemTextJson.JsonDiffPatch/JsonString.cs @@ -8,9 +8,7 @@ namespace System.Text.Json.JsonDiffPatch { internal struct JsonString { - internal static readonly JsonSerializerOptions SerializerOption; - - private static readonly JsonSerializerOptions SerializerOptions; + internal static readonly JsonSerializerOptions SerializerOptions; static JsonString() { From f6f54c3dacfbaa3c43e4da421d794c7f0b7a93d2 Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sat, 20 Jan 2024 15:30:31 +1300 Subject: [PATCH 5/8] Add 2.0 to release notes --- ReleaseNotes.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 8e0b1b9..46e7b21 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,5 +1,20 @@ # Release Notes +## 2.0.0 + +- **[BREAKING CHANGE]** Targeting framework changes: + - Added: .NET 8, .NET 7, .NET 6, .NET Framework 4.6.2 + - Removed: .NET Standard 2.1, .NET Framework 4.6.1 +- **[BREAKING CHANGE]** Minimum version of `System.Text.Json` required is bumped up to `8.0.0`. +- **[BREAKING CHANGE]** When targeting `net8.0`, the following methods are changed to be a wrapper of the methods introduced to `JsonNode` in [this issue](https://github.com/dotnet/runtime/issues/56592): + - `JsonDiffPatcher.DeepEquals(JsonNode)` + - `JsonDiffPatcher.DeepClone(JsonNode)` + + Those methods remain unchanged when targeting other frameworks + +- **[BREAKING CHANGE]** When targeting `net8.0`, `DeepClone` is no longer an extension method of `JsonNode`. The method is still accessible as static method from `JsonDiffPatcher` type, i.e. `JsonDiffPatcher.DeepClone` + + ## 1.3.1 - Added `PropertyFilter` to `JsonDiffOptions` (#29) From 0410e50b06b897ed9715ed8ac3f6e114e1d3c43e Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sat, 20 Jan 2024 15:39:12 +1300 Subject: [PATCH 6/8] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0947e19..8098d17 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ High-performance, low-allocating JSON object diff and patch extension for System - Compatible with [jsondiffpatch delta format](https://github.com/benjamine/jsondiffpatch/blob/master/docs/deltas.md) - Support generating patch document in RFC 6902 JSON Patch format -- Target latest **.NET Standard** and **.NET Framework 4.6.1** (for legacy apps) and leverage latest .NET features +- Support .NET and .NET Framework - Alternative to [jsondiffpatch.net](https://github.com/wbish/jsondiffpatch.net) which is based on Newtonsoft.Json - Fast large JSON document diffing with less memory consumption (see [benchmark](https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/Benchmark.md)) - Support smart array diffing (e.g. move detect) using LCS (Longest Common Subsequence) and custom array item matcher @@ -106,7 +106,7 @@ var textEqual = node1.DeepEquals(node2, JsonElementComparison.RawText); var semanticEqual = node1.DeepEquals(node2, JsonElementComparison.Semantic); ``` -### DeepClone +### DeepClone (.NET Framework and .NET 6 & 7) ```csharp var node = JsonNode.Parse("{\"foo\":\"bar\"}"); From 302c2a98537c9cca55daa12c6ce8737632347cff Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sun, 21 Jan 2024 21:02:30 +1300 Subject: [PATCH 7/8] Remove DeepClone method --- README.md | 10 +- ReleaseNotes.md | 22 ++-- src/Directory.Build.props | 4 - .../Diffs/JsonDiffDelta.cs | 8 +- .../JsonDiffPatcher.Clone.cs | 101 ------------------ .../JsonDiffPatcher.DeepEquals.cs | 6 +- .../Patching/JsonDiffPatcher.Patch.cs | 4 +- .../DeepCloneJsonFileBenchmark.cs | 22 ---- 8 files changed, 18 insertions(+), 159 deletions(-) delete mode 100644 src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs delete mode 100644 test/SystemTextJson.JsonDiffPatch.Benchmark/DeepCloneJsonFileBenchmark.cs diff --git a/README.md b/README.md index 8098d17..1ed55e9 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ High-performance, low-allocating JSON object diff and patch extension for System - Support smart array diffing (e.g. move detect) using LCS (Longest Common Subsequence) and custom array item matcher - _(Only when not using RFC 6902 format)_ Support diffing long text using [google-diff-match-patch](http://code.google.com/p/google-diff-match-patch/), or write your own diff algorithm - Bonus `DeepEquals` method for comparing `JsonDocument`, `JsonElement` and `JsonNode` -- Bonus `DeepClone` method - Bonus [`JsonValueComparer`](https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/src/SystemTextJson.JsonDiffPatch/JsonValueComparer.cs) that implements semantic comparison of two `JsonValue` objects - JSON assert for xUnit, MSTest v2 and NUnit with customizable delta output @@ -44,7 +43,7 @@ PM> Install-Package SystemTextJson.JsonDiffPatch.MSTest PM> Install-Package SystemTextJson.JsonDiffPatch.NUnit ``` -## Usage +## Examples ### Diff @@ -106,13 +105,6 @@ var textEqual = node1.DeepEquals(node2, JsonElementComparison.RawText); var semanticEqual = node1.DeepEquals(node2, JsonElementComparison.Semantic); ``` -### DeepClone (.NET Framework and .NET 6 & 7) - -```csharp -var node = JsonNode.Parse("{\"foo\":\"bar\"}"); -var cloned = node.DeepClone(); -``` - ### Default Options ```csharp diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 46e7b21..231e045 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -2,19 +2,17 @@ ## 2.0.0 -- **[BREAKING CHANGE]** Targeting framework changes: - - Added: .NET 8, .NET 7, .NET 6, .NET Framework 4.6.2 - - Removed: .NET Standard 2.1, .NET Framework 4.6.1 -- **[BREAKING CHANGE]** Minimum version of `System.Text.Json` required is bumped up to `8.0.0`. -- **[BREAKING CHANGE]** When targeting `net8.0`, the following methods are changed to be a wrapper of the methods introduced to `JsonNode` in [this issue](https://github.com/dotnet/runtime/issues/56592): - - `JsonDiffPatcher.DeepEquals(JsonNode)` - - `JsonDiffPatcher.DeepClone(JsonNode)` - - Those methods remain unchanged when targeting other frameworks - -- **[BREAKING CHANGE]** When targeting `net8.0`, `DeepClone` is no longer an extension method of `JsonNode`. The method is still accessible as static method from `JsonDiffPatcher` type, i.e. `JsonDiffPatcher.DeepClone` +- This version contains several **BREAKING CHANGES**: + - **Targeting framework changes**: + - Added: .NET 8, .NET 7, .NET 6, .NET Framework 4.6.2 + - Removed: .NET Standard 2.1, .NET Framework 4.6.1 + - Minimum version of `System.Text.Json` required is bumped up to `8.0.0` + - `JsonDiffPatcher.DeepEquals(JsonNode)` now simply calls `JsonNode.DeepEquals(JsonNode, JsonNode)` method introduced in [this issue](https://github.com/dotnet/runtime/issues/56592) + - `JsonDiffPatcher.Diff` method is unchanged because it does not use `JsonNode.DeepEquals(JsonNode, JsonNode)` method internally + - You can still use `JsonDiffPatcher.DeepEquals` method when invoked with custom comparison options + - When invoked against `JsonDocument` and `JsonElement`, `DeepEquals` method is unchanged + - Removed `JsonDiffPatcher.DeepClone` method. You can migrate to `JsonNode.DeepClone` method introduced in [this issue](https://github.com/dotnet/runtime/issues/56592) - ## 1.3.1 - Added `PropertyFilter` to `JsonDiffOptions` (#29) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 80b3025..4887eea 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -24,10 +24,6 @@ <FileVersion>1.0.0.0</FileVersion> </PropertyGroup> - <PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'"> - <DefineConstants>$(DefineConstants);HAVE_NEW_JSONNODE_METHODS</DefineConstants> - </PropertyGroup> - <ItemGroup> <None Include="..\..\icon.png" Link="Packaging\icon.png" Pack="true" PackagePath="\" /> <None Include="..\..\LICENSE" Link="Packaging\LICENSE" Pack="true" PackagePath="\" /> diff --git a/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs b/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs index 83df1d4..7cbd5dc 100644 --- a/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs +++ b/src/SystemTextJson.JsonDiffPatch/Diffs/JsonDiffDelta.cs @@ -244,22 +244,22 @@ public void Added(JsonNode? newValue) { EnsureDeltaType(nameof(Added), count: 1); var arr = Document!.AsArray(); - arr[0] = JsonDiffPatcher.DeepClone(newValue); + arr[0] = newValue?.DeepClone(); } public void Modified(JsonNode? oldValue, JsonNode? newValue) { EnsureDeltaType(nameof(Modified), count: 2); var arr = Document!.AsArray(); - arr[0] = JsonDiffPatcher.DeepClone(oldValue); - arr[1] = JsonDiffPatcher.DeepClone(newValue); + arr[0] = oldValue?.DeepClone(); + arr[1] = newValue?.DeepClone(); } public void Deleted(JsonNode? oldValue) { EnsureDeltaType(nameof(Deleted), count: 3, opType: OpTypeDeleted); var arr = Document!.AsArray(); - arr[0] = JsonDiffPatcher.DeepClone(oldValue); + arr[0] = oldValue?.DeepClone(); arr[1] = 0; } diff --git a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs b/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs deleted file mode 100644 index ff7613e..0000000 --- a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.Clone.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text.Json.Nodes; - -namespace System.Text.Json.JsonDiffPatch -{ - static partial class JsonDiffPatcher - { - /// <summary> - /// Creates a deep copy of the <see cref="JsonNode"/>. - /// </summary> - /// <param name="obj">The <see cref="JsonNode"/>.</param> -#if HAVE_NEW_JSONNODE_METHODS - public static T? DeepClone<T>(T? obj) where T : JsonNode -#else - public static T? DeepClone<T>(this T? obj) where T : JsonNode -#endif - { -#if HAVE_NEW_JSONNODE_METHODS - return obj is null ? null : (T)obj.DeepClone(); -#else - return (T?)(obj switch - { - null => (JsonNode?)null, - JsonObject jsonObj => new JsonObject(Enumerate(jsonObj), obj.Options), - JsonArray array => CloneArray(array), - JsonValue value => CloneJsonValue(value), - _ => throw new NotSupportedException( - $"JsonNode of type '{obj.GetType().Name}' is not supported.") - }); - - static IEnumerable<KeyValuePair<string, JsonNode?>> Enumerate(JsonObject obj) - { - foreach (var kvp in obj) - { - yield return new KeyValuePair<string, JsonNode?>(kvp.Key, DeepClone(kvp.Value)); - } - } -#endif - } - - private static JsonValue? CloneJsonValue(JsonValue? value) - { - if (value is null) - { - return null; - } - - if (value.TryGetValue<JsonElement>(out var element)) - return JsonValue.Create(element.Clone(), value.Options); - if (value.TryGetValue<int>(out var intValue)) - return JsonValue.Create(intValue, value.Options); - if (value.TryGetValue<long>(out var longValue)) - return JsonValue.Create(longValue, value.Options); - if (value.TryGetValue<double>(out var doubleValue)) - return JsonValue.Create(doubleValue, value.Options); - if (value.TryGetValue<short>(out var shortValue)) - return JsonValue.Create(shortValue, value.Options); - if (value.TryGetValue<decimal>(out var decimalValue)) - return JsonValue.Create(decimalValue, value.Options); - if (value.TryGetValue<byte>(out var byteValue)) - return JsonValue.Create(byteValue, value.Options); - if (value.TryGetValue<float>(out var floatValue)) - return JsonValue.Create(floatValue, value.Options); - if (value.TryGetValue<uint>(out var uintValue)) - return JsonValue.Create(uintValue, value.Options); - if (value.TryGetValue<ushort>(out var ushortValue)) - return JsonValue.Create(ushortValue, value.Options); - if (value.TryGetValue<ulong>(out var ulongValue)) - return JsonValue.Create(ulongValue, value.Options); - if (value.TryGetValue<sbyte>(out var sbyteValue)) - return JsonValue.Create(sbyteValue, value.Options); - if (value.TryGetValue<string>(out var stringValue)) - return JsonValue.Create(stringValue, value.Options); - if (value.TryGetValue<DateTime>(out var dateTimeValue)) - return JsonValue.Create(dateTimeValue, value.Options); - if (value.TryGetValue<DateTimeOffset>(out var dateTimeOffsetValue)) - return JsonValue.Create(dateTimeOffsetValue, value.Options); - if (value.TryGetValue<Guid>(out var guidValue)) - return JsonValue.Create(guidValue, value.Options); - if (value.TryGetValue<char>(out var charValue)) - return JsonValue.Create(charValue, value.Options); - if (value.TryGetValue<byte[]>(out var byteArrayValue)) - return JsonValue.Create(byteArrayValue, value.Options); - - // Perf: This is slower than direct property access - return JsonValue.Create(value.GetValue<object>(), value.Options); - } - - private static JsonArray CloneArray(JsonArray arr) - { - var newArr = new JsonArray(arr.Options); - foreach (var cloned in arr.Select(DeepClone)) - { - newArr.Add(cloned); - } - - return newArr; - } - } -} diff --git a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs b/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs index 9964815..bbcb02d 100644 --- a/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs +++ b/src/SystemTextJson.JsonDiffPatch/JsonDiffPatcher.DeepEquals.cs @@ -7,17 +7,13 @@ namespace System.Text.Json.JsonDiffPatch static partial class JsonDiffPatcher { /// <summary> - /// Determines whether two <see cref="JsonNode"/> objects are deeply equal. + /// Invokes <see cref="JsonNode.DeepEquals(JsonNode?, JsonNode?)" /> method. /// </summary> /// <param name="left">The left value.</param> /// <param name="right">The right value.</param> public static bool DeepEquals(this JsonNode? left, JsonNode? right) { -#if HAVE_NEW_JSONNODE_METHODS return JsonNode.DeepEquals(left, right); -#else - return DeepEquals(left, right, default(JsonComparerOptions)); -#endif } /// <summary> diff --git a/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs b/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs index f4e1c7b..f75b9ff 100644 --- a/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs +++ b/src/SystemTextJson.JsonDiffPatch/Patching/JsonDiffPatcher.Patch.cs @@ -52,7 +52,7 @@ when left is JsonValue jsonValue /// <param name="options">The patch options.</param> public static JsonNode? PatchNew(this JsonNode? left, JsonNode? patch, JsonPatchOptions options = default) { - var copy = DeepClone(left); + var copy = left?.DeepClone(); Patch(ref copy, patch, options); return copy; } @@ -105,7 +105,7 @@ when right is JsonValue jsonValue /// <param name="options">The patch options.</param> public static JsonNode? ReversePatchNew(this JsonNode? right, JsonNode? patch, JsonReversePatchOptions options = default) { - var copy = DeepClone(right); + var copy = right?.DeepClone(); ReversePatch(ref copy, patch, options); return copy; } diff --git a/test/SystemTextJson.JsonDiffPatch.Benchmark/DeepCloneJsonFileBenchmark.cs b/test/SystemTextJson.JsonDiffPatch.Benchmark/DeepCloneJsonFileBenchmark.cs deleted file mode 100644 index f27d956..0000000 --- a/test/SystemTextJson.JsonDiffPatch.Benchmark/DeepCloneJsonFileBenchmark.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.Json.JsonDiffPatch; -using System.Text.Json.Nodes; -using BenchmarkDotNet.Attributes; -using Newtonsoft.Json.Linq; - -namespace SystemTextJson.JsonDiffPatch.Benchmark -{ - public class DeepCloneJsonFileBenchmark : JsonFileBenchmark - { - [Benchmark] - public JsonNode SystemTextJson() - { - return JsonNode.Parse(JsonLeft).DeepClone()!; - } - - [Benchmark] - public JToken JsonNet() - { - return JToken.Parse(JsonLeft).DeepClone(); - } - } -} From cfdf58320032ff48e4eeb47a78463946552c8c3c Mon Sep 17 00:00:00 2001 From: Wei Chen <weichch87@gmail.com> Date: Sun, 21 Jan 2024 21:09:48 +1300 Subject: [PATCH 8/8] Include third party notice --- THIRD-PARTY-NOTICES.txt | 4 +++- src/Directory.Build.props | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt index 8c0b939..3d2deae 100644 --- a/THIRD-PARTY-NOTICES.txt +++ b/THIRD-PARTY-NOTICES.txt @@ -2,7 +2,9 @@ system-text-json-jsondiffpatch uses third-party libraries or other resources tha distributed under licenses different than system-text-json-jsondiffpatch. In the event that we accidentally failed to list a required notice, please -bring it to our attention. Please post an issue. +bring it to our attention. + +Please post an issue at https://github.com/weichch/system-text-json-jsondiffpatch/issues The attached notices are provided for information only. diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 4887eea..8cb48b8 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -27,6 +27,7 @@ <ItemGroup> <None Include="..\..\icon.png" Link="Packaging\icon.png" Pack="true" PackagePath="\" /> <None Include="..\..\LICENSE" Link="Packaging\LICENSE" Pack="true" PackagePath="\" /> + <None Include="..\..\THIRD-PARTY-NOTICES.txt" Link="Packaging\THIRD-PARTY-NOTICES.txt" Pack="true" PackagePath="\" /> </ItemGroup> </Project>