### Install SystemTextJson.JsonDiffPatch NuGet Packages Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Install the core diff/patch library and any desired test assertion packages via NuGet. ```shell dotnet add package SystemTextJson.JsonDiffPatch ``` ```shell dotnet add package SystemTextJson.JsonDiffPatch.Xunit ``` ```shell dotnet add package SystemTextJson.JsonDiffPatch.MSTest ``` ```shell dotnet add package SystemTextJson.JsonDiffPatch.NUnit ``` -------------------------------- ### JSON Assertions for Unit Testing in C# Source: https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/README.md Demonstrates how to use JsonAssert and assertion extensions for xUnit, MSTest, and NUnit to compare JSON objects. Ensure the correct assertion library is imported for your testing framework. ```csharp var expected = JsonNode.Parse("{\"foo\":\"bar\"}"); var actual = JsonNode.Parse("{\"baz\":\"qux\", \"foo\":\"bar3\"}"); // xUnit JsonAssert.Equal(expected, actual); actual.ShouldEqual(expected); JsonAssert.NotEqual(expected, actual); actual.ShouldNotEqual(expected); // MSTest JsonAssert.AreEqual(expected, actual); Assert.That.JsonAreEqual(expected, actual); JsonAssert.AreNotEqual(expected, actual); Assert.That.JsonAreNotEqual(expected, actual); // NUnit JsonAssert.AreEqual(expected, actual); Assert.That(actual, JsonIs.EqualTo(expected)); JsonAssert.AreNotEqual(expected, actual); Assert.That(actual, JsonIs.NotEqualTo(expected)); ``` -------------------------------- ### Configure Default Diff Options Source: https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/README.md Sets the default options for diff operations and the default comparison mode for DeepEquals. This allows for consistent behavior across multiple diff calls. ```csharp // Default diff options JsonDiffPatcher.DefaultOptions = () => new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }; ``` ```csharp // Default comparison mode for DeepEquals JsonDiffPatcher.DefaultComparison = JsonElementComparison.Semantic; ``` -------------------------------- ### xUnit JSON Assertions Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Provides `JsonAssert.Equal` / `NotEqual` and fluent extension methods `ShouldEqual` / `ShouldNotEqual` for xUnit tests, enabling assertions on JSON data structures. ```APIDOC ## xUnit JSON Assertions — `JsonAssert` (xUnit) The `SystemTextJson.JsonDiffPatch.Xunit` package provides `JsonAssert.Equal` / `NotEqual` and fluent extension methods `ShouldEqual` / `ShouldNotEqual` for xUnit tests. ### Usage ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.Xunit; using Xunit; public class MyApiTests { [Fact] public void Response_ShouldMatchExpected() { var expected = JsonNode.Parse(@"{{\"id\":1,\"name\":\"Alice\"}}"); var actual = JsonNode.Parse(@"{{\"id\":1,\"name\":\"Alice\"}}"); // Basic equality (throws JsonEqualException on failure) JsonAssert.Equal(expected, actual); // Fluent style actual.ShouldEqual(expected); // With diff output printed on failure JsonAssert.Equal(expected, actual, output: true); // With custom diff options (semantic comparison) var opts = new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }; JsonAssert.Equal(expected, actual, opts); // With custom output formatter JsonAssert.Equal(expected, actual, delta => $"Mismatch detected!\nDelta:\n{delta.ToJsonString()}"); // Not-equal assertion var other = JsonNode.Parse(@"{{\"id\":2}}"); JsonAssert.NotEqual(expected, other); other.ShouldNotEqual(expected); } } ``` ``` -------------------------------- ### xUnit JSON Assertions with JsonAssert Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Utilize JsonAssert.Equal/NotEqual and fluent extension methods for xUnit tests to compare JSON structures. Supports basic equality, semantic comparison, and custom output formatting. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.Xunit; using Xunit; public class MyApiTests { [Fact] public void Response_ShouldMatchExpected() { var expected = JsonNode.Parse("{\"id\":1,\"name\":\"Alice\"}"); var actual = JsonNode.Parse("{\"id\":1,\"name\":\"Alice\"}"); // Basic equality (throws JsonEqualException on failure) JsonAssert.Equal(expected, actual); // Fluent style actual.ShouldEqual(expected); // With diff output printed on failure JsonAssert.Equal(expected, actual, output: true); // With custom diff options (semantic comparison) var opts = new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }; JsonAssert.Equal(expected, actual, opts); // With custom output formatter JsonAssert.Equal(expected, actual, delta => $"Mismatch detected!\nDelta:\n{delta.ToJsonString()}"); // Not-equal assertion var other = JsonNode.Parse("{\"id\":2}"); JsonAssert.NotEqual(expected, other); other.ShouldNotEqual(expected); } } ``` -------------------------------- ### Set Global Defaults for JsonDiffPatcher Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Configure process-wide defaults for diff options and comparison modes. This avoids repetitive option passing in individual calls. ```csharp using System.Text.Json.JsonDiffPatch; // Apply semantic comparison globally for all Diff calls JsonDiffPatcher.DefaultOptions = () => new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic, TextDiffMinLength = 100, }; // Apply semantic comparison globally for all DeepEquals calls JsonDiffPatcher.DefaultComparison = JsonElementComparison.Semantic; // Now all Diff/DeepEquals calls use Semantic comparison by default var left = JsonNode.Parse("{ \"n\":1.0 }"); var right = JsonNode.Parse("{ \"n\":1 }"); JsonNode? delta = left.Diff(right); // null — semantically equal bool eq = left.DeepEquals(right); // true — semantically equal ``` -------------------------------- ### Diff JSON Objects and Files Source: https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/README.md Demonstrates various ways to generate a diff between JSON data. Supports JsonNode, files, spans, streams, strings, and readers. Options can be provided for custom comparison or RFC 6902 format. ```csharp // Diff JsonNode var node1 = JsonNode.Parse("{\"foo\":\"bar\"}"); var node2 = JsonNode.Parse("{\"baz\":\"qux\", \"foo\":\"bar\"}"); var diff = node1.Diff(node2); ``` ```csharp // Diff with options var diff = node1.Diff(node2, new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }); ``` ```csharp // Diff and convert delta into RFC 6902 JSON Patch format var diff = node1.Diff(node2, new JsonPatchDeltaFormatter()); ``` ```csharp // Diff JSON files var diff = JsonDiffPatcher.DiffFile(file1, file2); ``` ```csharp // Diff Span var diff = JsonDiffPatcher.Diff(span1, span2); ``` ```csharp // Diff streams var diff = JsonDiffPatcher.Diff(stream1, stream2); ``` ```csharp // Diff JSON strings var diff = JsonDiffPatcher.Diff(json1, json2); ``` ```csharp // Diff JSON readers var diff = JsonDiffPatcher.Diff(ref reader1, ref reader2); ``` -------------------------------- ### Global Defaults for Diff and DeepEquals Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Configure process-wide defaults for diff options and comparison modes. This allows you to set a default comparison strategy, such as `Semantic`, for all subsequent `Diff` and `DeepEquals` calls without needing to specify options each time. ```APIDOC ## `JsonDiffPatcher.DefaultOptions` / `DefaultComparison` — Global Defaults Set process-wide defaults for diff options and the `DeepEquals` comparison mode so individual call sites don't need to pass options every time. ```csharp using System.Text.Json.JsonDiffPatch; // Apply semantic comparison globally for all Diff calls JsonDiffPatcher.DefaultOptions = () => new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic, TextDiffMinLength = 100, }; // Apply semantic comparison globally for all DeepEquals calls JsonDiffPatcher.DefaultComparison = JsonElementComparison.Semantic; // Now all Diff/DeepEquals calls use Semantic comparison by default var left = JsonNode.Parse("""{"n":1.0}""" ); var right = JsonNode.Parse("""{"n":1}""" ); JsonNode? delta = left.Diff(right); // null — semantically equal bool eq = left.DeepEquals(right); // true — semantically equal ``` ``` -------------------------------- ### Apply Delta with JsonDiffPatcher.Patch and PatchNew Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Apply a delta document to a JSON node. `Patch` modifies the node in-place, while `PatchNew` returns a deep clone with the delta applied. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; var left = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":30 }"); var right = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":31,\"city\":\"London\" }"); JsonNode? delta = left.Diff(right); // In-place patch (mutates left) JsonNode? node = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":30 }"); JsonDiffPatcher.Patch(ref node, delta); Console.WriteLine(node); // {"name":"Alice","age":31,"city":"London"} // Clone-and-patch (leaves original untouched) var original = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":30 }"); JsonNode? patched = original.PatchNew(delta); Console.WriteLine(original); // {"name":"Alice","age":30} — unchanged Console.WriteLine(patched); // {"name":"Alice","age":31,"city":"London"} ``` -------------------------------- ### Apply Delta using Patch and PatchNew Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Apply a generated delta to a JSON node. `Patch` modifies the node in-place, while `PatchNew` applies the patch to a deep clone, leaving the original node unchanged. ```APIDOC ## `JsonDiffPatcher.Patch` / `PatchNew` — Apply a Delta Apply a delta document produced by `Diff` to a JSON node in-place (`Patch`) or to a deep clone (`PatchNew`). ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; var left = JsonNode.Parse("""{"name":"Alice","age":30}""" ); var right = JsonNode.Parse("""{"name":"Alice","age":31,"city":"London"}""" ); JsonNode? delta = left.Diff(right); // In-place patch (mutates left) JsonNode? node = JsonNode.Parse("""{"name":"Alice","age":30}""" ); JsonDiffPatcher.Patch(ref node, delta); Console.WriteLine(node); // {"name":"Alice","age":31,"city":"London"} // Clone-and-patch (leaves original untouched) var original = JsonNode.Parse("""{"name":"Alice","age":30}""" ); JsonNode? patched = original.PatchNew(delta); Console.WriteLine(original); // {"name":"Alice","age":30} — unchanged Console.WriteLine(patched); // {"name":"Alice","age":31,"city":"London"} ``` ``` -------------------------------- ### Undo Delta using ReversePatch and ReversePatchNew Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Reverse a previously applied patch to restore a JSON node to its original state. `ReversePatch` performs the reversal in-place, while `ReversePatchNew` returns a new node with the patch reversed. ```APIDOC ## `JsonDiffPatcher.ReversePatch` / `ReversePatchNew` — Undo a Delta Reverse a previously applied patch to restore a node to its original state. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; var left = JsonNode.Parse("""{"name":"Alice","age":30}""" ); var right = JsonNode.Parse("""{"name":"Alice","age":31,"city":"London"}""" ); JsonNode? delta = left.Diff(right); // Apply patch forward JsonNode? node = left.PatchNew(delta); Console.WriteLine(node); // {"name":"Alice","age":31,"city":"London"} // Reverse the patch (in-place) JsonDiffPatcher.ReversePatch(ref node, delta); Console.WriteLine(node); // {"name":"Alice","age":30} // Clone-and-unpatch JsonNode? restored = right.ReversePatchNew(delta); Console.WriteLine(restored); // {"name":"Alice","age":30} ``` ``` -------------------------------- ### NUnit JSON Assertions Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Utilize JsonAssert.AreEqual/AreNotEqual and constraint-based Assert.That(actual, JsonIs.EqualTo(expected)) for NUnit. Supports direct assertions, constraint-based assertions, and custom output formatters. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.Nunit; using NUnit.Framework; [TestFixture] public class MyNunitTests { [Test] public void Response_ShouldMatchExpected() { var expected = JsonNode.Parse(""{"items":[1,2,3]}"""); var actual = JsonNode.Parse(""{"items":[1,2,3]}"""); // Direct assertion JsonAssert.AreEqual(expected, actual); // Constraint-based (integrates with NUnit's fluent Assert.That) Assert.That(actual, JsonIs.EqualTo(expected)); // With diff options passed through the constraint builder var opts = new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }; Assert.That(actual, JsonIs.EqualTo(expected).WithDiffOptions(opts)); // With custom output formatter on failure Assert.That(actual, JsonIs.EqualTo(expected) .WithOutputFormatter(delta => $"Delta: {delta.ToJsonString()}")); // Not-equal constraint var other = JsonNode.Parse(""{"items":[4,5]}"""); JsonAssert.AreNotEqual(expected, other); Assert.That(other, JsonIs.NotEqualTo(expected)); } } ``` -------------------------------- ### JsonDiffPatcher.Diff with JsonDiffOptions - Customized Diffing Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Allows for customized JSON diffing using JsonDiffOptions to control array move detection, text diffing, element comparison, property filtering, and custom comparers. ```APIDOC ## JsonDiffPatcher.Diff with `JsonDiffOptions` ### Description `JsonDiffOptions` controls array move detection, long-text diffing, element comparison mode, property filtering, and custom value comparers. Pass an instance as the last argument to any `Diff` overload. ### Method `JsonNode.Diff(JsonNode? right, JsonDiffOptions options)` ### Parameters #### Request Body (Implicit via Options) - **options** (`JsonDiffOptions`) - An object to configure diffing behavior: - **JsonElementComparison** (`JsonElementComparison`) - Controls how JSON elements are compared (e.g., `Semantic` for value equivalence). - **PropertyFilter** (`Func`) - A predicate to filter properties during diffing. - **TextDiffMinLength** (`int`) - Minimum length for text diffing. - **SuppressDetectArrayMove** (`bool`) - Whether to suppress array move detection. - **ArrayItemMatcher** (`Func`) - Custom logic for matching array items. ### Request Example ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.Diffs; var left = JsonNode.Parse(@"{ \"ts\":\"2024-01-01\", \"value\":1.0, \"secret\":\"hidden\" }"); var right = JsonNode.Parse(@"{ \"ts\":\"2024-01-01T00:00:00\", \"value\":1, \"secret\":\"changed\" }"); var options = new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic, PropertyFilter = (propertyName, context) => propertyName != "secret", TextDiffMinLength = 50, SuppressDetectArrayMove = false, ArrayItemMatcher = (ref ArrayItemMatchContext ctx) => { if (ctx.Left is JsonObject lo && ctx.Right is JsonObject ro && lo["id"]?.GetValue() == ro["id"]?.GetValue()) { ctx.DeepEqual(); return true; } return false; }, }; JsonNode? delta = left.Diff(right, options); Console.WriteLine(delta is null ? "Equal (with options)" : delta.ToJsonString()); ``` ### Response #### Success Response (200) - **delta** (`JsonNode?`) - A `JsonNode` representing the differences based on the provided options, or `null` if no differences are found. #### Response Example ```json Equal (with options) ``` ``` -------------------------------- ### Patch and Unpatch JSON Data Source: https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/README.md Shows how to apply a generated diff to modify JSON data (patch) or revert changes (unpatch). Supports in-place modification or creating a new patched object. ```csharp var node1 = JsonNode.Parse("{\"foo\":\"bar\"}"); var node2 = JsonNode.Parse("{\"baz\":\"qux\", \"foo\":\"bar\"}"); var diff = node1.Diff(node2); // In-place patch JsonDiffPatcher.Patch(ref node1, diff); ``` ```csharp // Clone & patch var patched = node1.PatchNew(diff); ``` ```csharp // In-place unpatch JsonDiffPatcher.ReversePatch(ref node1, diff); ``` ```csharp // Clone & unpatch var patched = node1.ReversePatchNew(diff); ``` -------------------------------- ### Undo Delta with JsonDiffPatcher.ReversePatch and ReversePatchNew Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Reverse a previously applied patch to restore a JSON node to its original state. `ReversePatch` modifies in-place, `ReversePatchNew` returns a new restored node. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; var left = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":30 }"); var right = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":31,\"city\":\"London\" }"); JsonNode? delta = left.Diff(right); // Apply patch forward JsonNode? node = left.PatchNew(delta); Console.WriteLine(node); // {"name":"Alice","age":31,"city":"London"} // Reverse the patch (in-place) JsonDiffPatcher.ReversePatch(ref node, delta); Console.WriteLine(node); // {"name":"Alice","age":30} // Clone-and-unpatch JsonNode? restored = right.ReversePatchNew(delta); Console.WriteLine(restored); // {"name":"Alice","age":30} ``` -------------------------------- ### Diff Two JSON Nodes using SystemTextJson.JsonDiffPatch Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Compares two JsonNode objects and returns a delta document compatible with the jsondiffpatch delta format. Returns null if the nodes are equal. Overloads support various input types including strings, byte spans, streams, and files. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; var left = JsonNode.Parse诬{"name":"Alice","age":30,"roles":["admin"]}"); var right = JsonNode.Parse诬{"name":"Alice","age":31,"roles":["admin","editor"]}"); // Returns null when equal; returns a delta JsonNode when different JsonNode? delta = left.Diff(right); if (delta is null) { Console.WriteLine("No differences found."); } else { // Delta format compatible with jsondiffpatch Console.WriteLine(delta.ToJsonString(new JsonSerializerOptions { WriteIndented = true })); // Output: // { // "age": [30, 31], // "roles": { // "_t": "a", // "1": ["editor"] // } // } } // Diff from JSON strings directly JsonNode? delta2 = JsonDiffPatcher.Diff( "{\"foo\":\"bar\"}", "{\"foo\":\"baz\",\"extra\":1}" ); // Diff from files JsonNode? fileDelta = JsonDiffPatcher.DiffFile("left.json", "right.json"); // Diff from byte spans (zero-allocation path) ReadOnlySpan spanLeft = "{\"x\":1}"u8; ReadOnlySpan spanRight = "{\"x\":2}"u8; JsonNode? spanDelta = JsonDiffPatcher.Diff(spanLeft, spanRight); ``` ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.Diffs; var left = JsonNode.Parse诬{"ts":"2024-01-01","value":1.0,"secret":"hidden"}"); var right = JsonNode.Parse诬{"ts":"2024-01-01T00:00:00","value":1,"secret":"changed"}"); var options = new JsonDiffOptions { // Treat "1.0" and "1", or "2024-01-01" and "2024-01-01T00:00:00" as equal JsonElementComparison = JsonElementComparison.Semantic, // Ignore the "secret" property entirely PropertyFilter = (propertyName, context) => propertyName != "secret", // Enable long-text diffing for strings >= 50 chars using google-diff-match-patch TextDiffMinLength = 50, // Suppress array move detection (treat moves as delete+add) SuppressDetectArrayMove = false, // Custom array item matcher: match objects by their "id" field ArrayItemMatcher = (ref ArrayItemMatchContext ctx) => { if (ctx.Left is JsonObject lo && ctx.Right is JsonObject ro && lo["id"]?.GetValue() == ro["id"]?.GetValue()) { ctx.DeepEqual(); // mark as deeply equal if all other fields match return true; // these items match } return false; }, }; JsonNode? delta = left.Diff(right, options); // delta is null because "ts" and "value" are semantically equal, // and "secret" is filtered out Console.WriteLine(delta is null ? "Equal (with options)" : delta.ToJsonString()); ``` -------------------------------- ### MSTest v2 JSON Assertions Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Use JsonAssert.AreEqual/AreNotEqual and Assert.That.JsonAreEqual for MSTest v2. Supports direct assertions, assertions with output on failure, and assertions with custom diff options. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.MsTest; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class MyMsTests { [TestMethod] public void Response_ShouldMatchExpected() { var expected = JsonNode.Parse(""{"status":"ok","count":3}"""); var actual = JsonNode.Parse(""{"status":"ok","count":3}"""); // Direct assertion JsonAssert.AreEqual(expected, actual); // With output on failure JsonAssert.AreEqual(expected, actual, output: true); // Via Assert extension method Assert.That.JsonAreEqual(expected, actual); // With diff options var opts = new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }; JsonAssert.AreEqual(expected, actual, opts); // Not-equal assertion var other = JsonNode.Parse(""{"status":"error"}"""); JsonAssert.AreNotEqual(expected, other); Assert.That.JsonAreNotEqual(expected, other); } } ``` -------------------------------- ### Deep Equality Comparison for JSON Source: https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/README.md Compares JSON structures for equality using different modes: raw text, semantic, or default. Supports JsonDocument and JsonNode. ```csharp // JsonDocument var doc1 = JsonDocument.Parse("{\"foo\":1}"); var doc2 = JsonDocument.Parse("{\"foo\":1.0}"); var equal = doc1.DeepEquals(doc2); var textEqual = doc1.DeepEquals(doc2, JsonElementComparison.RawText); var semanticEqual = doc1.DeepEquals(doc2, JsonElementComparison.Semantic); ``` ```csharp // JsonNode var node1 = JsonNode.Parse("{\"foo\":1}"); var node2 = JsonNode.Parse("{\"foo\":1.0}"); var equal = node1.DeepEquals(node2); var textEqual = node1.DeepEquals(node2, JsonElementComparison.RawText); var semanticEqual = node1.DeepEquals(node2, JsonElementComparison.Semantic); ``` -------------------------------- ### Generate RFC 6902 JSON Patch with JsonPatchDeltaFormatter Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Obtain an RFC 6902 JSON Patch array instead of the default jsondiffpatch delta format. Supports custom options. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.Diffs.Formatters; var left = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":30 }"); var right = JsonNode.Parse("{ \"name\":\"Alice\",\"age\":31,\"city\":\"London\" }"); // Returns JsonNode representing a RFC 6902 patch array JsonNode? patch = left.Diff(right, new JsonPatchDeltaFormatter()); Console.WriteLine(patch?.ToJsonString(new JsonSerializerOptions { WriteIndented = true })); // Output: // [ // { "op": "replace", "path": "/age", "value": 31 }, // { "op": "add", "path": "/city", "value": "London" } // ] // Overload with options var options = new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }; JsonNode? patch2 = left.Diff(right, new JsonPatchDeltaFormatter(), options); ``` -------------------------------- ### Semantic Value Comparison Source: https://github.com/weichch/system-text-json-jsondiffpatch/blob/main/README.md Compares JSON values semantically, treating numbers with different decimal representations as equal and dates in string format as equal. Useful for ignoring minor formatting differences. ```csharp var node1 = JsonNode.Parse("\"2019-11-27\""); var node2 = JsonNode.Parse("\"2019-11-27T00:00:00.000\""); // dateCompare is 0 var dateCompare = JsonValueComparer.Compare(node1, node2); ``` ```csharp var node3 = JsonNode.Parse("1"); var node4 = JsonNode.Parse("1.00"); // numCompare is 0 var numCompare = JsonValueComparer.Compare(node3, node4); ``` -------------------------------- ### RFC 6902 JSON Patch Output using JsonPatchDeltaFormatter Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Generate diffs in the standard RFC 6902 JSON Patch format instead of the default jsondiffpatch format. This is useful when interoperating with systems that expect RFC 6902 compliant patches. ```APIDOC ## `JsonDiffPatcher.Diff` with `JsonPatchDeltaFormatter` — RFC 6902 JSON Patch Output Use `JsonPatchDeltaFormatter` to obtain a standard RFC 6902 JSON Patch array instead of the jsondiffpatch delta format. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; using System.Text.Json.JsonDiffPatch.Diffs.Formatters; var left = JsonNode.Parse("""{"name":"Alice","age":30}""" ); var right = JsonNode.Parse("""{"name":"Alice","age":31,"city":"London"}""" ); // Returns JsonNode representing a RFC 6902 patch array JsonNode? patch = left.Diff(right, new JsonPatchDeltaFormatter()); Console.WriteLine(patch?.ToJsonString(new JsonSerializerOptions { WriteIndented = true })); // Output: // [ // { "op": "replace", "path": "/age", "value": 31 }, // { "op": "add", "path": "/city", "value": "London" } // ] // Overload with options var options = new JsonDiffOptions { JsonElementComparison = JsonElementComparison.Semantic }; JsonNode? patch2 = left.Diff(right, new JsonPatchDeltaFormatter(), options); ``` ``` -------------------------------- ### JsonDiffPatcher.Diff - Diff Two JSON Nodes Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Compares two JsonNode objects and returns a delta document. It handles various input types including strings, byte spans, streams, and JsonNodes. Returns null if the nodes are identical. ```APIDOC ## JsonDiffPatcher.Diff ### Description Compares two `JsonNode?` objects and returns a delta document (`JsonNode?`). Returns `null` if the two nodes are equal. Overloads accept `string`, `ReadOnlySpan`, `Stream`, `Utf8JsonReader`, or `JsonNode` inputs. ### Method `JsonNode.Diff(JsonNode? right)` `JsonDiffPatcher.Diff(string leftJson, string rightJson)` `JsonDiffPatcher.DiffFile(string leftFilePath, string rightFilePath)` `JsonDiffPatcher.Diff(ReadOnlySpan left, ReadOnlySpan right)` ### Request Example ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; var left = JsonNode.Parse(@"{ \"name\":\"Alice\", \"age\":30, \"roles\":[\"admin\"] }"); var right = JsonNode.Parse(@"{ \"name\":\"Alice\", \"age\":31, \"roles\":[\"admin\",\"editor\"] }"); JsonNode? delta = left.Diff(right); if (delta is null) { Console.WriteLine("No differences found."); } else { Console.WriteLine(delta.ToJsonString(new JsonSerializerOptions { WriteIndented = true })); } // Diff from JSON strings directly JsonNode? delta2 = JsonDiffPatcher.Diff( @"{ \"foo\":\"bar\" }", @"{ \"foo\":\"baz\", \"extra\":1 }" ); // Diff from files JsonNode? fileDelta = JsonDiffPatcher.DiffFile("left.json", "right.json"); // Diff from byte spans (zero-allocation path) ReadOnlySpan spanLeft = @"{ \"x\":1 }"u8; ReadOnlySpan spanRight = @"{ \"x\":2 }"u8; JsonNode? spanDelta = JsonDiffPatcher.Diff(spanLeft, spanRight); ``` ### Response #### Success Response (200) - **delta** (`JsonNode?`) - A `JsonNode` representing the differences, or `null` if no differences are found. #### Response Example ```json { "age": [30, 31], "roles": { "_t": "a", "1": ["editor"] } } ``` ``` -------------------------------- ### JsonValueComparer.Compare Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Compares two `JsonValue` instances semantically, treating numerically or temporally equivalent values as equal. Returns negative, zero, or positive like standard `IComparer`. ```APIDOC ## `JsonValueComparer.Compare` — Semantic Comparison of JsonValue Compares two `JsonValue` instances semantically, treating numerically or temporally equivalent values as equal. Returns negative, zero, or positive like standard `IComparer`. ### Usage ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; // Date string comparison var date1 = JsonNode.Parse("\"2019-11-27\")")!.AsValue(); var date2 = JsonNode.Parse("\"2019-11-27T00:00:00.000\")")!.AsValue(); int dateCmp = JsonValueComparer.Compare(date1, date2); Console.WriteLine(dateCmp); // 0 — semantically equal dates // Numeric comparison var num1 = JsonNode.Parse("1")!.AsValue(); var num2 = JsonNode.Parse("1.00")!.AsValue(); int numCmp = JsonValueComparer.Compare(num1, num2); Console.WriteLine(numCmp); // 0 — semantically equal numbers // Integer ordering var a = JsonNode.Parse("5")!.AsValue(); var b = JsonNode.Parse("10")!.AsValue(); Console.WriteLine(JsonValueComparer.Compare(a, b)); // negative (5 < 10) Console.WriteLine(JsonValueComparer.Compare(b, a)); // positive (10 > 5) // Use as a custom IEqualityComparer inside JsonDiffOptions var options = new JsonDiffOptions { ValueComparer = EqualityComparer.Create( (x, y) => JsonValueComparer.Compare(x, y) == 0, x => x.GetHashCode() ) }; ``` ``` -------------------------------- ### DeepEquals for JsonNode, JsonDocument, JsonElement Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Use DeepEquals to determine structural equality of JSON values. Supports RawText or Semantic comparison modes. Property order does not affect equality for JsonNode. ```csharp using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; // --- JsonNode --- var n1 = JsonNode.Parse("{\"a\":1,\"b\":[1,2]}"); var n2 = JsonNode.Parse("{\"b\":[1,2],\"a\":1}"); // property order differs bool eq1 = n1.DeepEquals(n2); // true — order-insensitive bool eq2 = n1.DeepEquals(n2, JsonElementComparison.Semantic); // true // Numeric semantic equality: 1 == 1.00 var x = JsonNode.Parse("1"); var y = JsonNode.Parse("1.00"); Console.WriteLine(x.DeepEquals(y)); // false (RawText) Console.WriteLine(x.DeepEquals(y, JsonElementComparison.Semantic)); // true // --- JsonDocument --- using var doc1 = JsonDocument.Parse("{\"foo\":1}"); using var doc2 = JsonDocument.Parse("{\"foo\":1.0}"); Console.WriteLine(doc1.DeepEquals(doc2)); // false (RawText) Console.WriteLine(doc1.DeepEquals(doc2, JsonElementComparison.Semantic)); // true // --- JsonElement --- JsonElement elem1 = JsonDocument.Parse("{\"k\":\"2024-01-01\"}").RootElement; JsonElement elem2 = JsonDocument.Parse("{\"k\":\"2024-01-01\"}").RootElement; Console.WriteLine(elem1.DeepEquals(elem2)); // true ``` -------------------------------- ### JsonDiffPatcher.DeepEquals Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Determines structural equality of two JSON values (`JsonNode`, `JsonDocument`, `JsonElement`). Supports optional `RawText` (default) or `Semantic` comparison modes. ```APIDOC ## `JsonDiffPatcher.DeepEquals` — Deep Equality for JsonNode, JsonDocument, JsonElement Determines structural equality of two JSON values. Supports `JsonNode`, `JsonDocument`, and `JsonElement`, with optional `RawText` (default) or `Semantic` comparison modes. ### Usage ```csharp using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; // --- JsonNode --- var n1 = JsonNode.Parse(@"{{\"a\":1,\"b\":[1,2]}}"); var n2 = JsonNode.Parse(@"{{\"b\":[1,2],\"a\":1}}"); // property order differs bool eq1 = n1.DeepEquals(n2); // true — order-insensitive bool eq2 = n1.DeepEquals(n2, JsonElementComparison.Semantic); // true // Numeric semantic equality: 1 == 1.00 var x = JsonNode.Parse("1"); var y = JsonNode.Parse("1.00"); Console.WriteLine(x.DeepEquals(y)); // false (RawText) Console.WriteLine(x.DeepEquals(y, JsonElementComparison.Semantic)); // true // --- JsonDocument --- using var doc1 = JsonDocument.Parse(@"{{\"foo\":1}}"); using var doc2 = JsonDocument.Parse(@"{{\"foo\":1.0}}"); Console.WriteLine(doc1.DeepEquals(doc2)); // false (RawText) Console.WriteLine(doc1.DeepEquals(doc2, JsonElementComparison.Semantic)); // true // --- JsonElement --- JsonElement elem1 = JsonDocument.Parse(@"{{\"k\":\"2024-01-01\"}}").RootElement; JsonElement elem2 = JsonDocument.Parse(@"{{\"k\":\"2024-01-01\"}}").RootElement; Console.WriteLine(elem1.DeepEquals(elem2)); // true ``` ``` -------------------------------- ### JsonValueComparer for Semantic Comparison Source: https://context7.com/weichch/system-text-json-jsondiffpatch/llms.txt Use JsonValueComparer.Compare to semantically compare JsonValue instances, treating numerically or temporally equivalent values as equal. This can be used to create custom IEqualityComparer for JsonDiffOptions. ```csharp using System.Text.Json.Nodes; using System.Text.Json.JsonDiffPatch; // Date string comparison var date1 = JsonNode.Parse(" \"2019-11-27\" ")!.AsValue(); var date2 = JsonNode.Parse(" \"2019-11-27T00:00:00.000\" ")!.AsValue(); int dateCmp = JsonValueComparer.Compare(date1, date2); Console.WriteLine(dateCmp); // 0 — semantically equal dates // Numeric comparison var num1 = JsonNode.Parse("1")!.AsValue(); var num2 = JsonNode.Parse("1.00")!.AsValue(); int numCmp = JsonValueComparer.Compare(num1, num2); Console.WriteLine(numCmp); // 0 — semantically equal numbers // Integer ordering var a = JsonNode.Parse("5")!.AsValue(); var b = JsonNode.Parse("10")!.AsValue(); Console.WriteLine(JsonValueComparer.Compare(a, b)); // negative (5 < 10) Console.WriteLine(JsonValueComparer.Compare(b, a)); // positive (10 > 5) // Use as a custom IEqualityComparer inside JsonDiffOptions var options = new JsonDiffOptions { ValueComparer = EqualityComparer.Create( (x, y) => JsonValueComparer.Compare(x, y) == 0, x => x.GetHashCode() ) }; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.