/// <summary> /// The "replace" operation replaces the value at the target location /// with a new value. The operation object MUST contain a "value" member /// whose content specifies the replacement value. /// /// The target location MUST exist for the operation to be successful. /// /// For example: /// /// { "op": "replace", "path": "/a/b/c", "value": 42 } /// /// This operation is functionally identical to a "remove" operation for /// a value, followed immediately by an "add" operation at the same /// location with the replacement value. /// /// Note: even though it's the same functionally, we do not call remove + add /// for performance reasons (multiple checks of same requirements). /// </summary> /// <param name="operation">The replace operation.</param> /// <param name="objectToApplyTo">Object to apply the operation to.</param> public void Replace(Operation operation, object objectToApplyTo) { if (operation == null) { throw new ArgumentNullException(nameof(operation)); } if (objectToApplyTo == null) { throw new ArgumentNullException(nameof(objectToApplyTo)); } var parsedPath = new ParsedPath(operation.path); var visitor = new ObjectVisitor(parsedPath, ContractResolver); IAdapter adapter; var target = objectToApplyTo; string errorMessage; if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage); ErrorReporter(error); return; } if (!adapter.TryReplace(target, parsedPath.LastSegment, ContractResolver, operation.value, out errorMessage)) { var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, errorMessage); ErrorReporter(error); return; } }
private bool TryGetValue( string fromLocation, object objectToGetValueFrom, Operation operation, out object propertyValue) { if (fromLocation == null) { throw new ArgumentNullException(nameof(fromLocation)); } if (objectToGetValueFrom == null) { throw new ArgumentNullException(nameof(objectToGetValueFrom)); } if (operation == null) { throw new ArgumentNullException(nameof(operation)); } propertyValue = null; var parsedPath = new ParsedPath(fromLocation); var visitor = new ObjectVisitor(parsedPath, ContractResolver); IAdapter adapter; var target = objectToGetValueFrom; string errorMessage; if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { var error = CreatePathNotFoundError(objectToGetValueFrom, fromLocation, operation, errorMessage); ErrorReporter(error); return(false); } if (!adapter.TryGet(target, parsedPath.LastSegment, ContractResolver, out propertyValue, out errorMessage)) { var error = CreateOperationFailedError(objectToGetValueFrom, fromLocation, operation, errorMessage); ErrorReporter(error); return(false); } return(true); }
/// <summary> /// Remove is used by various operations (eg: remove, move, ...), yet through different operations; /// This method allows code reuse yet reporting the correct operation on error. The return value /// contains the type of the item that has been removed (and a bool possibly signifying an error) /// This can be used by other methods, like replace, to ensure that we can pass in the correctly /// typed value to whatever method follows. /// </summary> private void Remove(string path, object objectToApplyTo, Operation operationToReport) { var parsedPath = new ParsedPath(path); var visitor = new ObjectVisitor(parsedPath, ContractResolver); IAdapter adapter; var target = objectToApplyTo; string errorMessage; if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, path, operationToReport, errorMessage); ErrorReporter(error); return; } if (!adapter.TryRemove(target, parsedPath.LastSegment, ContractResolver, out errorMessage)) { var error = CreateOperationFailedError(objectToApplyTo, path, operationToReport, errorMessage); ErrorReporter(error); return; } }