Merge pull request #46 from RyanObray/master

Property Filter and Patch Behavior Solution (Resolves #34)
pull/56/head
William Bishop 2020-11-27 21:16:49 -06:00 committed by GitHub
commit cf577b1753
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 129 additions and 19 deletions

View File

@ -1,4 +1,5 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
@ -296,6 +297,6 @@ namespace JsonDiffPatchDotNet.UnitTests
Assert.AreEqual(2, array.Count);
Assert.AreEqual(left, array[0]);
Assert.AreEqual(right, array[1]);
}
}
}
}

View File

@ -1,4 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
@ -246,6 +247,61 @@ namespace JsonDiffPatchDotNet.UnitTests
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());
}
}
}

View File

@ -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
}
}

View File

@ -1,5 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using DiffMatchPatch;
@ -43,15 +44,15 @@ namespace JsonDiffPatchDotNet
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
@ -66,8 +67,10 @@ namespace JsonDiffPatchDotNet
: null;
}
if (!JToken.DeepEquals(left, right))
return new JArray(left, right);
if (!JToken.DeepEquals(left, right))
{
return new JArray(left, right);
}
return null;
}
@ -324,10 +327,21 @@ namespace JsonDiffPatchDotNet
// 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)));
@ -343,8 +357,8 @@ namespace JsonDiffPatchDotNet
// 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)));

View File

@ -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;
@ -23,6 +27,16 @@
/// 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; }
}
}