/// <summary> /// Patch a JSON object /// </summary> /// <param name="left">Unpatched JSON object</param> /// <param name="patch">JSON Patch Document</param> /// <returns>Patched JSON object</returns> /// <exception cref="System.IO.InvalidDataException">Thrown if the patch document is invalid</exception> public JToken Patch(JToken left, JToken patch) { if (patch == null) return left; if (patch.Type == JTokenType.Object) { var patchObj = (JObject)patch; JProperty arrayDiffCanary = patchObj.Property("_t"); if (left != null && left.Type == JTokenType.Array && arrayDiffCanary != null && arrayDiffCanary.Value.Type == JTokenType.String && arrayDiffCanary.ToObject<string>() == "a") { return ArrayPatch((JArray)left, patchObj); } return ObjectPatch(left as JObject, patchObj); } if (patch.Type == JTokenType.Array) { var patchArray = (JArray)patch; if (patchArray.Count == 1) // Add { return patchArray[0]; } else if (patchArray.Count == 2) // Replace { return patchArray[1]; } else if (patchArray.Count == 3) // Delete, Move or TextDiff { if (patchArray[2].Type != JTokenType.Integer) throw new InvalidDataException("Invalid patch object"); int op = patchArray[2].Value<int>(); if (op == 0) { return null; } else if (op == 2) { var dmp = new diff_match_patch(); List<Patch> patches = dmp.patch_fromText(patchArray[0].ToObject<string>()); if (patches.Count != 1) throw new InvalidDataException("Invalid textline"); string right = dmp.diff_text2(patches[0].diffs); return right; } else { throw new InvalidDataException("Invalid patch object"); } } else { throw new InvalidDataException("Invalid patch object"); } } return null; }