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>