protected static DeltaType GetDeltaType(JToken delta = null, MoveDestination movedFrom = null) { if (delta == null) { return(movedFrom != null ? DeltaType.MoveDestination : DeltaType.Unchanged); } switch (delta.Type) { case JTokenType.Array: { var deltaArray = (JArray)delta; switch (deltaArray.Count) { case 1: return(DeltaType.Added); case 2: return(DeltaType.Modified); case 3: { switch ((DiffOperation)deltaArray[2].Value <int>()) { case DiffOperation.Deleted: return(DeltaType.Deleted); case DiffOperation.TextDiff: return(DeltaType.TextDiff); case DiffOperation.ArrayMove: return(DeltaType.Moved); } break; } } break; } case JTokenType.Object: return(DeltaType.Node); } return(DeltaType.Unknown); }
protected void ForEachDeltaKey(JToken delta, JToken left, DeltaKeyIterator iterator) { var keys = new List <string>(); var arrayKeys = false; var movedDestinations = new Dictionary <string, MoveDestination>(); if (delta is JObject jObject) { keys = jObject.Properties().Select(p => p.Name).ToList(); arrayKeys = jObject["_t"]?.Value <string>() == "a"; } if (left != null && left is JObject leftObject) { foreach (var kvp in leftObject) { if (delta[kvp.Key] == null && (!arrayKeys || delta["_" + kvp.Key] == null)) { keys.Add(kvp.Key); } } } if (delta is JObject deltaObject) { foreach (var kvp in deltaObject) { var value = kvp.Value; if (value is JArray valueArray && valueArray.Count == 3) { var diffOp = valueArray[2].Value <int>(); if (diffOp == (int)DiffOperation.ArrayMove) { var moveKey = valueArray[1].ToString(); movedDestinations[moveKey] = new MoveDestination(kvp.Key, left?[kvp.Key.Substring(1)]); if (IncludeMoveDestinations && left == null && deltaObject.Property(moveKey) == null) { keys.Add(moveKey); } } } } } if (arrayKeys) { keys.Sort(s_arrayKeyComparer); } else { keys.Sort(); } for (var index = 0; index < keys.Count; index++) { var key = keys[index]; if (arrayKeys && key == "_t") { continue; } var leftKey = arrayKeys ? key.TrimStart('_') : key; var isLast = index == keys.Count - 1; var movedFrom = movedDestinations.ContainsKey(leftKey) ? movedDestinations[leftKey] : null; iterator(key, leftKey, movedFrom, isLast); } }
protected void Recurse(TContext context, JToken delta, JToken left, string key, string leftKey, MoveDestination movedFrom, bool isLast) { var useMoveOriginHere = delta != null && movedFrom != null; var leftValue = useMoveOriginHere ? movedFrom.Value : left; if (delta == null && string.IsNullOrEmpty(key)) { return; } var type = GetDeltaType(delta, movedFrom); var nodeType = type == DeltaType.Node ? (delta["_t"]?.Value <string>() == "a" ? NodeType.Array : NodeType.Object) : NodeType.Unknown; if (!string.IsNullOrEmpty(key)) { NodeBegin(context, key, leftKey, type, nodeType, isLast); } else { RootBegin(context, type, nodeType); } Format(type, context, delta, leftValue, key, leftKey, movedFrom); if (!string.IsNullOrEmpty(key)) { NodeEnd(context, key, leftKey, type, nodeType, isLast); } else { RootEnd(context, type, nodeType); } }
protected abstract void Format(DeltaType type, TContext context, JToken delta, JToken leftValue, string key, string leftKey, MoveDestination movedFrom);