Skip to content

Commit

Permalink
Merge pull request #46 from RyanObray/master
Browse files Browse the repository at this point in the history
Property Filter and Patch Behavior Solution (Resolves #34)
  • Loading branch information
wbish authored Nov 28, 2020
2 parents a0508be + c40cf5d commit cf577b1
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 19 deletions.
5 changes: 3 additions & 2 deletions Src/JsonDiffPatchDotNet.UnitTests/DiffUnitTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
Expand Down Expand Up @@ -296,6 +297,6 @@ public void Diff_IntStringDiff_ValidPatch()
Assert.AreEqual(2, array.Count);
Assert.AreEqual(left, array[0]);
Assert.AreEqual(right, array[1]);
}
}
}
}
60 changes: 58 additions & 2 deletions Src/JsonDiffPatchDotNet.UnitTests/PatchUnitTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using NUnit.Framework;

Expand Down Expand Up @@ -246,6 +247,61 @@ public void Patch_Bug17EfficienText_Success()
var patched = jdp.Patch(left, patch);

Assert.IsTrue(JToken.DeepEquals(right.ToString(), patched.ToString()));
}
}

[Test]
public void Diff_ExcludePaths_ValidPatch()
{
var jdp = new JsonDiffPatch(new Options { ExcludePaths = new List<string>() { "id", "nested.id" } });
var left = JObject.Parse(@"{ ""id"": ""pid"", ""p"": ""old"", ""nested"": { ""id"":""nid"", ""p"":""old"" } }");
var right = JObject.Parse(@"{ ""id"": ""pid2"", ""p"": ""new"", ""nested"": { ""id"":""nid2"", ""p"":""new"" } }");
var expected = JObject.Parse(@"{ ""id"": ""pid"", ""p"": ""new"", ""nested"": { ""id"":""nid"", ""p"":""new"" } }");
var patch = jdp.Diff(left, right);
var patched = jdp.Patch(left, patch) as JObject;

Assert.AreEqual(expected.ToString(), patched.ToString());
}

[Test]
public void Diff_Behaviors_IgnoreMissingProperties_ValidPatch()
{
var jdp = new JsonDiffPatch(new Options { DiffBehaviors = DiffBehavior.IgnoreMissingProperties });
var left = JObject.Parse(@"{ ""id"": ""pid"", ""p"": ""old"", ""nested"": { ""id"":""nid"", ""p"":""old"" } }");
var right = JObject.Parse(@"{ ""p"": ""new"", ""nested"": { ""p"":""new"" }, ""newP"": ""new"" }");
var expected = JObject.Parse(@"{ ""id"": ""pid"", ""p"": ""new"", ""nested"": { ""id"":""nid"", ""p"":""new"" }, ""newP"": ""new"" }");
var patch = jdp.Diff(left, right);
var patched = jdp.Patch(left, patch) as JObject;

Assert.AreEqual(expected.ToString(), patched.ToString());
}

[Test]
public void Diff_Behaviors_IgnoreNewProperties_ValidPatch()
{
var jdp = new JsonDiffPatch(new Options { DiffBehaviors = DiffBehavior.IgnoreNewProperties });
var left = JObject.Parse(@"{ ""id"": ""pid"", ""p"": ""old"", ""nested"": { ""id"":""nid"", ""p"":""old"" } }");
var right = JObject.Parse(@"{ ""id"": ""pid2"", ""p"": ""new"", ""nested"": { ""id"":""nid2"", ""p"":""new"" }, ""newP"": ""new"" }");
var expected = JObject.Parse(@"{ ""id"": ""pid2"", ""p"": ""new"", ""nested"": { ""id"":""nid2"", ""p"":""new"" } }");
var patch = jdp.Diff(left, right);
var patched = jdp.Patch(left, patch) as JObject;

Assert.AreEqual(expected.ToString(), patched.ToString());
}

[Test]
public void Diff_ExludeAndBehaviors_ExcludeIgnoreMissingIgnoreNew_ValidPatch()
{
var jdp = new JsonDiffPatch(new Options {
ExcludePaths = new List<string>() { "id", "nested.id" },
DiffBehaviors = DiffBehavior.IgnoreMissingProperties | DiffBehavior.IgnoreNewProperties
});
var left = JObject.Parse(@"{ ""id"": ""pid"", ""p"": ""old"", ""nested"": { ""id"":""nid"", ""p"":""old"" } }");
var right = JObject.Parse(@"{ ""id"": ""pid2"", ""nested"": { ""id"":""nid2"" }, ""newP"": ""new"" }");
var expected = JObject.Parse(@"{ ""id"": ""pid"", ""p"": ""old"", ""nested"": { ""id"":""nid"", ""p"":""old"" } }");
var patch = jdp.Diff(left, right);
var patched = jdp.Patch(left, patch) as JObject;

Assert.AreEqual(expected.ToString(), patched.ToString());
}
}
}
25 changes: 25 additions & 0 deletions Src/JsonDiffPatchDotNet/DiffBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JsonDiffPatchDotNet
{
[Flags]
public enum DiffBehavior
{
/// <summary>
/// Default behavior
/// </summary>
None,
/// <summary>
/// If the patch document is missing properties that are in the source document, leave the existing properties in place instead of deleting them
/// </summary>
IgnoreMissingProperties,
/// <summary>
/// If the patch document contains properties that aren't defined in the source document, ignore them instead of adding them
/// </summary>
IgnoreNewProperties
}
}
38 changes: 26 additions & 12 deletions Src/JsonDiffPatchDotNet/JsonDiffPatch.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using DiffMatchPatch;
Expand Down Expand Up @@ -43,15 +44,15 @@ public JToken Diff(JToken left, JToken right)
right = new JValue("");

if (left.Type == JTokenType.Object && right.Type == JTokenType.Object)
{
return ObjectDiff((JObject)left, (JObject)right);
{
return ObjectDiff((JObject)left, (JObject)right);
}

if (_options.ArrayDiff == ArrayDiffMode.Efficient
&& left.Type == JTokenType.Array
&& right.Type == JTokenType.Array)
{
return ArrayDiff((JArray)left, (JArray)right);
{
return ArrayDiff((JArray)left, (JArray)right);
}

if (_options.TextDiff == TextDiffMode.Efficient
Expand All @@ -66,8 +67,10 @@ public JToken Diff(JToken left, JToken right)
: null;
}

if (!JToken.DeepEquals(left, right))
return new JArray(left, right);
if (!JToken.DeepEquals(left, right))
{
return new JArray(left, right);
}

return null;
}
Expand Down Expand Up @@ -324,10 +327,21 @@ private JObject ObjectDiff(JObject left, JObject right)

// Find properties modified or deleted
foreach (var lp in left.Properties())
{
JProperty rp = right.Property(lp.Name);
{
//Skip property if in path exclustions
if (_options.ExcludePaths.Count > 0 && _options.ExcludePaths.Any(p => p.Equals(lp.Path, StringComparison.OrdinalIgnoreCase)))
{
continue;
}

JProperty rp = right.Property(lp.Name);

// Property deleted
if (rp == null && (_options.DiffBehaviors & DiffBehavior.IgnoreMissingProperties) == DiffBehavior.IgnoreMissingProperties)
{
continue;
}

// Property deleted
if (rp == null)
{
diffPatch.Add(new JProperty(lp.Name, new JArray(lp.Value, 0, (int)DiffOperation.Deleted)));
Expand All @@ -343,8 +357,8 @@ private JObject ObjectDiff(JObject left, JObject right)

// Find properties that were added
foreach (var rp in right.Properties())
{
if (left.Property(rp.Name) != null)
{
if (left.Property(rp.Name) != null || (_options.DiffBehaviors & DiffBehavior.IgnoreNewProperties) == DiffBehavior.IgnoreNewProperties)
continue;

diffPatch.Add(new JProperty(rp.Name, new JArray(rp.Value)));
Expand Down
20 changes: 17 additions & 3 deletions Src/JsonDiffPatchDotNet/Options.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
namespace JsonDiffPatchDotNet
using System;
using System.Collections;
using System.Collections.Generic;

namespace JsonDiffPatchDotNet
{
public sealed class Options
{
{
public Options()
{
ArrayDiff = ArrayDiffMode.Efficient;
Expand All @@ -23,6 +27,16 @@ public Options()
/// The minimum string length required to use Efficient text diff. If the minimum
/// length is not met, simple text diff will be used. The default length is 50 characters.
/// </summary>
public long MinEfficientTextDiffLength { get; set; }
public long MinEfficientTextDiffLength { get; set; }

/// <summary>
/// Specifies which paths to exclude from the diff patch set
/// </summary>
public List<string> ExcludePaths { get; set; } = new List<string>();

/// <summary>
/// Specifies behaviors to apply to the diff patch set
/// </summary>
public DiffBehavior DiffBehaviors { get; set; }
}
}

0 comments on commit cf577b1

Please sign in to comment.