protected JsonMemberInfo GetMemberInfo(JsonPath path, JToken data, JsonMemberInfo parent) { var info = new JsonMemberInfo { Value = data.ToString(), Parent = parent, Path = path }; if (data.Type == JTokenType.Array) { info.Children = new SortedDictionary<string, JsonMemberInfo>(); info.IsArray = true; var idx = 0; foreach (var entry in ((IList<JToken>)data)) { var key = idx.ToString(CultureInfo.InvariantCulture); var newPath = new JsonPath { Property = key, IsIndexer = true }; newPath.Prev = path.Clone(newPath); info.Children.Add(key, this.GetMemberInfo(newPath, entry, info)); idx++; } } if (data.Type == JTokenType.Object) { info.Children = new SortedDictionary<string, JsonMemberInfo>(); info.IsObject = true; foreach (var entry in ((IDictionary<string, JToken>)data)) { var newPath = new JsonPath { Property = entry.Key, IsIndexer = false }; newPath.Prev = path.Clone(newPath); info.Children.Add(entry.Key, this.GetMemberInfo(newPath, entry.Value, info)); } } if (data.Type == JTokenType.Boolean) { info.Value = Convert.ToBoolean(data.ToString()); } if (data.Type == JTokenType.Float) { info.Value = Convert.ToDouble(data.ToString()); } if (data.Type == JTokenType.Integer) { info.Value = Convert.ToInt32(data.ToString()); } if (data.Type == JTokenType.Guid) { info.Value = new Guid(data.ToString()); } if (data.Type == JTokenType.String) { info.Value = Convert.ToString(data.ToString()); } if (data.Type == JTokenType.Null) { info.Value = null; } if (data.Type == JTokenType.Date) { info.Value = DateTime.Parse(data.ToString()); } return info; }
public string ApplyPatch(IEnumerable<JsonPatchBase> patches, string json) { var graph = _serializer.Deserialize(json); if (patches == null) { return json; } foreach (var patch in patches) { if (patch.Operation == JsonDiffPatchOperation.Remove) { var root = patch.Path.GetRoot(); var memberInfo = graph.FindByPath(root, patch.Path); if (memberInfo != null) { if (memberInfo.Parent != null) { memberInfo.Parent.Children.Remove(memberInfo.Parent.Children.Single(x => x.Value == memberInfo).Key); } else { if (memberInfo == graph) { graph = new JsonMemberInfo { Path = new JsonPath { Property = "$" } }; } else { throw new Exception("Invalid JSON Graph Structure!"); } } } else { throw new Exception("Invalid JSON Structure!"); } } if (patch.Operation == JsonDiffPatchOperation.Add) { if (patch.Element is int) { var root = patch.Path.GetRoot(); var memberInfo = graph.FindByPath(root, patch.Path); if (memberInfo != null) { if (memberInfo.IsArray) { var key = Convert.ToString(patch.Element); if (!memberInfo.Children.ContainsKey(key)) { var info = new JsonMemberInfo { Parent = memberInfo, Path = new JsonPath { IsIndexer = true, Property = key }, Value = patch.Value }; info.Path.Prev = memberInfo.Path.Clone(info.Path); memberInfo.Children.Add(key, info); } else { throw new Exception("Invalid JSON Structure! Index already exists."); } } else { throw new Exception("Invalid JSON Structure! Not an Array."); } } else { throw new Exception("Invalid JSON Structure!"); } } if (patch.Element is string) { var root = patch.Path.GetRoot(); var memberInfo = graph.FindByPath(root, patch.Path); if (memberInfo != null) { if (memberInfo.IsObject) { var key = Convert.ToString(patch.Element); if (!memberInfo.Children.ContainsKey(key)) { var info = new JsonMemberInfo { Parent = memberInfo, Path = new JsonPath { IsIndexer = false, Property = key }, Value = patch.Value }; info.Path.Prev = memberInfo.Path.Clone(info.Path); memberInfo.Children.Add(key, info); } else { throw new Exception("Invalid JSON Structure! Property already exists."); } } else { throw new Exception("Invalid JSON Structure! Not an Object."); } } else { throw new Exception("Invalid JSON Structure!"); } } } } return graph.ToJson(this._serializer); }