Replicate reordering of remove operations from source codebase
parent
7f193e8bd8
commit
0f51947b82
|
@ -6,10 +6,7 @@ namespace JsonDiffPatchDotNet.Formatters
|
|||
{
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
// This purposefully REVERSED from benjamine/jsondiffpatch,
|
||||
// In order to match logic found in JsonDiffPatch.ArrayPatch,
|
||||
// which applies operations in reverse order to avoid shifting floor
|
||||
return ArrayKeyToSortNumber(y) - ArrayKeyToSortNumber(x);
|
||||
return ArrayKeyToSortNumber(x) - ArrayKeyToSortNumber(y);
|
||||
}
|
||||
|
||||
private static int ArrayKeyToSortNumber(string key)
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace JsonDiffPatchDotNet.Formatters
|
|||
|
||||
private static readonly IComparer<string> s_arrayKeyComparer = new ArrayKeyComparer();
|
||||
|
||||
public TResult Format(JToken delta)
|
||||
public virtual TResult Format(JToken delta)
|
||||
{
|
||||
var context = new TContext();
|
||||
Recurse(context, delta, left: null, key: null, leftKey: null, movedFrom: null, isLast: false);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace JsonDiffPatchDotNet.Formatters.JsonPatch
|
||||
|
@ -8,6 +9,12 @@ namespace JsonDiffPatchDotNet.Formatters.JsonPatch
|
|||
{
|
||||
protected override bool IncludeMoveDestinations => true;
|
||||
|
||||
public override IList<Operation> Format(JToken delta)
|
||||
{
|
||||
var result = base.Format(delta);
|
||||
return ReorderOps(result);
|
||||
}
|
||||
|
||||
protected override void Format(DeltaType type, JsonFormatContext context, JToken delta, JToken leftValue, string key, string leftKey, MoveDestination movedFrom)
|
||||
{
|
||||
switch (type)
|
||||
|
@ -81,5 +88,44 @@ namespace JsonDiffPatchDotNet.Formatters.JsonPatch
|
|||
{
|
||||
context.PushMoveOp(delta[1].ToString());
|
||||
}
|
||||
|
||||
private IList<Operation> ReorderOps(IList<Operation> result)
|
||||
{
|
||||
var removeOpsOtherOps = PartitionRemoveOps(result);
|
||||
var removeOps = removeOpsOtherOps[0];
|
||||
var otherOps = removeOpsOtherOps[1];
|
||||
Array.Sort(removeOps, new RemoveOperationComparer());
|
||||
return removeOps.Concat(otherOps).ToList();
|
||||
}
|
||||
|
||||
private IList<Operation[]> PartitionRemoveOps(IList<Operation> result)
|
||||
{
|
||||
var left = new List<Operation>();
|
||||
var right = new List<Operation>();
|
||||
|
||||
foreach (var op in result)
|
||||
(op.Op.Equals("remove", StringComparison.Ordinal) ? left : right).Add(op);
|
||||
|
||||
return new List<Operation[]> {left.ToArray(), right.ToArray()};
|
||||
}
|
||||
|
||||
private class RemoveOperationComparer : IComparer<Operation>
|
||||
{
|
||||
public int Compare(Operation a, Operation b)
|
||||
{
|
||||
if (a == null) throw new ArgumentNullException(nameof(a));
|
||||
if (b == null) throw new ArgumentNullException(nameof(b));
|
||||
|
||||
var splitA = a.Path.Split('/');
|
||||
var splitB = b.Path.Split('/');
|
||||
|
||||
return splitA.Length != splitB.Length
|
||||
? splitA.Length - splitB.Length
|
||||
: CompareByIndexDesc(splitA.Last(), splitB.Last());
|
||||
}
|
||||
|
||||
private static int CompareByIndexDesc(string indexA, string indexB)
|
||||
=> int.TryParse(indexA, out var a) && int.TryParse(indexB, out var b) ? b - a : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue