private static ObjectDiffPatchResult Diff(JObject source, JObject target) { ObjectDiffPatchResult result = new ObjectDiffPatchResult(); // check for null values if (source == null && target == null) { return(result); } else if (source == null || target == null) { result.OldValues = source; result.NewValues = target; return(result); } // compare internal fields JArray removedNew = new JArray(); JArray removedOld = new JArray(); JToken token; // start by iterating in source fields foreach (var i in source) { // check if field exists if (!target.TryGetValue(i.Key, out token)) { AddOldValuesToken(result, i.Value, i.Key); removedNew.Add(i.Key); } // compare field values else { DiffField(i.Key, i.Value, token, result); } } // then iterate in target fields that are not present in source foreach (var i in target) { // ignore alredy compared values if (source.TryGetValue(i.Key, out token)) { continue; } // add missing tokens removedOld.Add(i.Key); AddNewValuesToken(result, i.Value, i.Key); } if (removedOld.Count > 0) { AddOldValuesToken(result, removedOld, PREFIX_REMOVED_FIELDS); } if (removedNew.Count > 0) { AddNewValuesToken(result, removedNew, PREFIX_REMOVED_FIELDS); } return(result); }
private static void AddOldValuesToken(ObjectDiffPatchResult item, JToken oldToken, string fieldName) { if (item.OldValues == null) { item.OldValues = new Newtonsoft.Json.Linq.JObject(); } item.OldValues[fieldName] = oldToken; }
private static void AddToken(ObjectDiffPatchResult item, string fieldName, ObjectDiffPatchResult diff) { AddToken(item, fieldName, diff.OldValues, diff.NewValues); }
private static void AddToken(ObjectDiffPatchResult item, string fieldName, JToken oldToken, JToken newToken) { AddOldValuesToken(item, oldToken, fieldName); AddNewValuesToken(item, newToken, fieldName); }
private static ObjectDiffPatchResult DiffField(string fieldName, JToken source, JToken target, ObjectDiffPatchResult result = null) { if (result == null) { result = new ObjectDiffPatchResult(); } if (source == null) { if (target != null) { AddToken(result, fieldName, source, target); } } else if (target == null) { AddToken(result, fieldName, source, target); } else if (source.Type == Newtonsoft.Json.Linq.JTokenType.Object) { var v = target as Newtonsoft.Json.Linq.JObject; var r = Diff(source as Newtonsoft.Json.Linq.JObject, v); if (!r.AreEqual) { AddToken(result, fieldName, r); } } else if (source.Type == Newtonsoft.Json.Linq.JTokenType.Array) { var aS = (source as Newtonsoft.Json.Linq.JArray); var aT = (target as Newtonsoft.Json.Linq.JArray); if ((aS.Count == 0 || aT.Count == 0) && (aS.Count != aT.Count)) { AddToken(result, fieldName, source, target); } else { ObjectDiffPatchResult arrayDiff = new ObjectDiffPatchResult(); int minCount = Math.Min(aS.Count, aT.Count); for (int i = 0; i < Math.Max(aS.Count, aT.Count); i++) { if (i < minCount) { DiffField(i.ToString(), aS[i], aT[i], arrayDiff); } else if (i >= aS.Count) { AddNewValuesToken(arrayDiff, aT[i], i.ToString()); } else { AddOldValuesToken(arrayDiff, aS[i], i.ToString()); } } if (!arrayDiff.AreEqual) { if (aS.Count != aT.Count) { AddToken(arrayDiff, PREFIX_ARRAY_SIZE, aS.Count, aT.Count); } AddToken(result, fieldName, arrayDiff); } } } else { if (!Newtonsoft.Json.Linq.JObject.DeepEquals(source, target)) { AddToken(result, fieldName, source, target); } } return(result); }