private static ObjectDeltaResult Delta(JObject source, JObject target) { var result = new ObjectDeltaResult(); // check for null values if (source == null && target == null) { return(result); } if (source == null || target == null) { result.OldValues = source; result.NewValues = target; return(result); } // compare internal fields var removedNew = new JArray(); var 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 { DeltaField(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(ObjectDeltaResult item, JToken oldToken, string fieldName) { if (item.OldValues == null) { item.OldValues = new JObject(); } item.OldValues[fieldName] = oldToken; }
public static T PatchObject <T>(T source, ObjectDeltaResult deltaResult) where T : class { var patched = PatchObject(source, deltaResult.OldValues); return(PatchObject(patched, deltaResult.NewValues)); }
private static void AddToken(ObjectDeltaResult item, string fieldName, ObjectDeltaResult delta) { AddToken(item, fieldName, delta.OldValues, delta.NewValues); }
private static void AddToken(ObjectDeltaResult item, string fieldName, JToken oldToken, JToken newToken) { AddOldValuesToken(item, oldToken, fieldName); AddNewValuesToken(item, newToken, fieldName); }
private static void DeltaField(string fieldName, JToken source, JToken target, ObjectDeltaResult result = null) { if (result == null) { result = new ObjectDeltaResult(); } if (source == null) { if (target != null) { AddToken(result, fieldName, source, target); } } else if (target == null) { AddToken(result, fieldName, source, target); } else { switch (source.Type) { case JTokenType.Object: var v = target as JObject; var r = Delta(source as JObject, v); if (!r.AreEqual) { AddToken(result, fieldName, r); } break; case JTokenType.Array: var aS = source as JArray; var aT = target as JArray; if ((aS.Count == 0 || aT.Count == 0) && (aS.Count != aT.Count)) { AddToken(result, fieldName, source, target); } else { var arrayDelta = new ObjectDeltaResult(); var minCount = Math.Min(aS.Count, aT.Count); for (var i = 0; i < Math.Max(aS.Count, aT.Count); i++) { if (i < minCount) { DeltaField(i.ToString(), aS[i], aT[i], arrayDelta); } else if (i >= aS.Count) { AddNewValuesToken(arrayDelta, aT[i], i.ToString()); } else { AddOldValuesToken(arrayDelta, aS[i], i.ToString()); } } if (arrayDelta.AreEqual) { return; } if (aS.Count != aT.Count) { AddToken(arrayDelta, PREFIX_ARRAY_SIZE, aS.Count, aT.Count); } AddToken(result, fieldName, arrayDelta); } break; default: if (!JToken.DeepEquals(source, target)) { AddToken(result, fieldName, source, target); } break; } } }