static bool TestEqual(MutableJsonValue value, JsonElement expected) { switch (value) { case MutableJsonObject @object: { if (expected.ValueKind != JsonValueKind.Object) { return(false); } foreach (var pair in @object) { if (!expected.TryGetProperty(pair.Key, out var expectedValue)) { return(false); } if (!TestEqual(pair.Value, expectedValue)) { return(false); } } return(true); } case MutableJsonArray array: { if (expected.ValueKind != JsonValueKind.Array) { return(false); } if (array.Count != expected.GetArrayLength()) { return(false); } for (int x = 0; x < array.Count; x++) { if (!TestEqual(array[x], expected[x])) { return(false); } } return(true); } case MutableJsonElement element: { // TODO: make this more efficient return(element.Element.GetRawText() == expected.GetRawText()); } default: return(false); } }
// TODO: consider replacing this with something more appropriate /// <summary> /// Attempts to apply the patches specified to the given root element. /// </summary> /// <param name="writer"> /// The writer to write the resultant document to. /// </param> /// <param name="rootElement"> /// The root element to apply the JSON Patch to. /// </param> /// <returns> /// <c>true</c> if the patch applied, or <c>false</c> otherwise. /// </returns> public bool TryApply(Utf8JsonWriter writer, JsonElement rootElement) { var tree = MutableJsonValue.Build(rootElement); if (!ApplyInternal(PatchElements, tree)) { return(false); } tree.WriteTo(writer); return(true); }
private static bool ApplyInternal(IEnumerable <PatchElement> elements, MutableJsonValue tree) { foreach (var patchElement in elements) { switch (patchElement) { case PatchAddElement add: { var state = (tree, add.Path.Depth, MutableJsonValue.Build(add.Value.RootElement)); if (!add.Path.Evaluate(AddElement, ref state)) { return(false); } break; } case PatchRemoveElement remove: { var state = (tree, remove.Path.Depth); if (!remove.Path.Evaluate(RemoveElement, ref state)) { return(false); } break; } case PatchReplaceElement replace: { var removeState = (tree, replace.Path.Depth); if (!replace.Path.Evaluate(RemoveElement, ref removeState)) { return(false); } var addState = (tree, replace.Path.Depth, MutableJsonValue.Build(replace.Value.RootElement)); if (!replace.Path.Evaluate(AddElement, ref addState)) { return(false); } break; } case PatchMoveElement move: { var removeState = (tree, move.From.Depth); if (!move.From.Evaluate(RemoveElement, ref removeState)) { return(false); } var addState = (tree, move.Path.Depth, removeState.tree); if (!move.Path.Evaluate(AddElement, ref addState)) { return(false); } break; } case PatchCopyElement copy: { var findState = tree; if (!copy.From.Evaluate(FindElement, ref findState)) { return(false); } var addState = (tree, copy.Path.Depth, findState); if (!copy.Path.Evaluate(AddElement, ref addState)) { return(false); } break; } case PatchTestElement test: { var findState = tree; if (!test.Path.Evaluate(FindElement, ref findState)) { return(false); } if (!TestEqual(findState, test.Value.RootElement)) { return(false); } break; } } } return(true);