Implement Replace Move and Copy for dynamic objects

This commit is contained in:
KevinDockx 2015-09-03 09:56:01 +02:00 committed by Ryan Nowak
parent ae57844c6a
commit 894574d04e
8 changed files with 1657 additions and 217 deletions

View File

@ -359,73 +359,30 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
public void Move([NotNull] Operation operation, [NotNull] object objectToApplyTo)
{
// get value at from location
object valueAtFromLocation = null;
var positionAsInteger = -1;
var actualFromProperty = operation.from;
var valueAtFromLocationResult = GetValueAtLocation(operation.from, objectToApplyTo, operation);
positionAsInteger = GetNumericEnd(operation.from);
if (positionAsInteger > -1)
{
actualFromProperty = operation.from.Substring(0,
operation.from.IndexOf('/' + positionAsInteger.ToString()));
}
var patchProperty = FindPropertyAndParent(objectToApplyTo, actualFromProperty);
// does property at from exist?
if (!CheckIfPropertyExists(patchProperty, objectToApplyTo, operation, operation.from))
if (valueAtFromLocationResult.HasError)
{
// Error has already been logged in GetValueAtLocation. We
// must return, because remove / add should not be allowed to continue
return;
}
// is the path an array (but not a string (= char[]))? In this case,
// the path must end with "/position" or "/-", which we already determined before.
if (positionAsInteger > -1)
{
if (IsNonStringArray(patchProperty.Property.PropertyType))
{
// now, get the generic type of the IList<> from Property type.
var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType);
// get value (it can be cast, we just checked that)
var array = (IList)patchProperty.Property.ValueProvider.GetValue(patchProperty.Parent);
if (array.Count <= positionAsInteger)
{
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatInvalidIndexForArrayProperty(operation.op, operation.from)));
return;
}
valueAtFromLocation = array[positionAsInteger];
}
else
{
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatInvalidPathForArrayProperty(operation.op, operation.from)));
return;
}
}
else
{
// no list, just get the value
// set the new value
valueAtFromLocation = patchProperty.Property.ValueProvider.GetValue(patchProperty.Parent);
}
// remove that value
Remove(operation.from, objectToApplyTo, operation);
var removeResult = Remove(operation.from, objectToApplyTo, operation);
if (removeResult.HasError)
{
// Return => error has already been logged in remove method. We must
// return, because add should not be allowed to continue
return;
}
// add that value to the path location
Add(operation.path, valueAtFromLocation, objectToApplyTo, operation);
Add(operation.path,
valueAtFromLocationResult.PropertyValue,
objectToApplyTo,
operation);
}
/// <summary>
@ -648,7 +605,7 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
Resources.FormatInvalidIndexForArrayProperty(
operationToReport.op,
path)));
return null;
return new RemovedPropertyTypeResult(null, true);
}
array.RemoveAt(positionAsInteger);
@ -706,8 +663,37 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
public void Replace([NotNull] Operation operation, [NotNull] object objectToApplyTo)
{
Remove(operation.path, objectToApplyTo, operation);
Add(operation.path, operation.value, objectToApplyTo, operation);
var removeResult = Remove(operation.path, objectToApplyTo, operation);
if (removeResult.HasError)
{
// return => error has already been logged in remove method
return;
}
if (!removeResult.HasError && removeResult.ActualType == null)
{
// the remove operation completed succesfully, but we could not determine the type.
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatCannotDeterminePropertyType(operation.from)));
return;
}
var conversionResult = ConvertToActualType(removeResult.ActualType, operation.value);
if (!conversionResult.CanBeConverted)
{
// invalid value for path
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatInvalidValueForProperty(operation.value, operation.path)));
return;
}
Add(operation.path, conversionResult.ConvertedInstance, objectToApplyTo, operation);
}
/// <summary>
@ -734,100 +720,183 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
public void Copy([NotNull] Operation operation, [NotNull] object objectToApplyTo)
{
// get value at from location
object valueAtFromLocation = null;
var positionAsInteger = -1;
var actualFromProperty = operation.from;
// get value at from location and add that value to the path location
var valueAtFromLocationResult = GetValueAtLocation(operation.from, objectToApplyTo, operation);
positionAsInteger = GetNumericEnd(operation.from);
if (positionAsInteger > -1)
{
actualFromProperty = operation.from.Substring(0,
operation.from.IndexOf('/' + positionAsInteger.ToString()));
}
var patchProperty = FindPropertyAndParent(objectToApplyTo, actualFromProperty);
// does property at from exist?
if (!CheckIfPropertyExists(patchProperty, objectToApplyTo, operation, operation.from))
if (valueAtFromLocationResult.HasError)
{
// Return, error has already been logged in GetValueAtLocation
return;
}
// get the property path
// is the path an array (but not a string (= char[]))? In this case,
// the path must end with "/position" or "/-", which we already determined before.
if (positionAsInteger > -1)
Add(operation.path,
valueAtFromLocationResult.PropertyValue,
objectToApplyTo,
operation);
}
/// <summary>
/// Method is used by Copy and Move to avoid duplicate code
/// </summary>
/// <param name="location">Location where value should be</param>
/// <param name="objectToGetValueFrom">Object to inspect for the desired value</param>
/// <param name="operationToReport">Operation to report in case of an error</param>
/// <returns>GetValueResult containing value and a bool signifying a possible error</returns>
private GetValueResult GetValueAtLocation(
[NotNull] string location,
[NotNull] object objectToGetValueFrom,
[NotNull] Operation operationToReport)
{
// get path result
var pathResult = GetActualPropertyPath(
location,
objectToGetValueFrom,
operationToReport);
if (pathResult == null)
{
if (IsNonStringArray(patchProperty.Property.PropertyType))
return new GetValueResult(null, true);
}
var getAtEndOfList = pathResult.ExecuteAtEnd;
var positionAsInteger = pathResult.NumericEnd;
var actualPathToProperty = pathResult.PathToProperty;
var treeAnalysisResult = new ObjectTreeAnalysisResult(
objectToGetValueFrom,
actualPathToProperty,
ContractResolver);
if (treeAnalysisResult.UseDynamicLogic)
{
// if it's not an array, we can remove the property from
// the dictionary. If it's an array, we need to check the position first.
if (getAtEndOfList || positionAsInteger > -1)
{
// now, get the generic type of the IList<> from Property type.
var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType);
var propertyValue = treeAnalysisResult.Container
.GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent);
// get value (it can be cast, we just checked that)
var array = (IList)patchProperty.Property.ValueProvider.GetValue(patchProperty.Parent);
if (array.Count <= positionAsInteger)
// we cannot continue when the value is null, because to be able to
// continue we need to be able to check if the array is a non-string array
if (propertyValue == null)
{
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatInvalidIndexForArrayProperty(operation.op, operation.from)));
return;
objectToGetValueFrom,
operationToReport,
Resources.FormatCannotDeterminePropertyType(location)));
return new GetValueResult(null, true);
}
valueAtFromLocation = array[positionAsInteger];
var typeOfPathProperty = propertyValue.GetType();
if (!IsNonStringArray(typeOfPathProperty))
{
LogError(new JsonPatchError(
objectToGetValueFrom,
operationToReport,
Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, location)));
return new GetValueResult(null, true);
}
// get the array
var array = (IList)treeAnalysisResult.Container.GetValueForCaseInsensitiveKey(
treeAnalysisResult.PropertyPathInParent);
if (positionAsInteger >= array.Count)
{
LogError(new JsonPatchError(
objectToGetValueFrom,
operationToReport,
Resources.FormatInvalidIndexForArrayProperty(
operationToReport.op,
location)));
return new GetValueResult(null, true);
}
if (getAtEndOfList)
{
return new GetValueResult(array[array.Count-1], false);
}
else
{
return new GetValueResult(array[positionAsInteger], false);
}
}
else
{
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatInvalidPathForArrayProperty(operation.op, operation.from)));
// get the property
var propertyValueAtLocation = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey(
treeAnalysisResult.PropertyPathInParent);
return;
}
return new GetValueResult(propertyValueAtLocation, false);
}
}
else
{
// no list, just get the value
// set the new value
valueAtFromLocation = patchProperty.Property.ValueProvider.GetValue(patchProperty.Parent);
// not dynamic
var patchProperty = treeAnalysisResult.JsonPatchProperty;
if (getAtEndOfList || positionAsInteger > -1)
{
if (!IsNonStringArray(patchProperty.Property.PropertyType))
{
LogError(new JsonPatchError(
objectToGetValueFrom,
operationToReport,
Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, location)));
return new GetValueResult(null, true);
}
if (!patchProperty.Property.Readable)
{
LogError(new JsonPatchError(
objectToGetValueFrom,
operationToReport,
Resources.FormatCannotReadProperty(location)));
return new GetValueResult(null, true);
}
var array = (IList)patchProperty.Property.ValueProvider
.GetValue(patchProperty.Parent);
if (positionAsInteger >= array.Count)
{
LogError(new JsonPatchError(
objectToGetValueFrom,
operationToReport,
Resources.FormatInvalidIndexForArrayProperty(
operationToReport.op,
location)));
return new GetValueResult(null, true);
}
if (getAtEndOfList)
{
return new GetValueResult(array[array.Count - 1], false);
}
else
{
return new GetValueResult(array[positionAsInteger], false);
}
}
else
{
if (!patchProperty.Property.Readable)
{
LogError(new JsonPatchError(
objectToGetValueFrom,
operationToReport,
Resources.FormatCannotReadProperty(
location)));
return new GetValueResult(null, true);
}
var propertyValueAtLocation = patchProperty.Property.ValueProvider
.GetValue(patchProperty.Parent);
return new GetValueResult(propertyValueAtLocation, false);
}
}
// add operation to target location with that value.
Add(operation.path, valueAtFromLocation, objectToApplyTo, operation);
}
private bool CheckIfPropertyExists(
JsonPatchProperty patchProperty,
object objectToApplyTo,
Operation operation,
string propertyPath)
{
if (patchProperty == null)
{
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatPropertyDoesNotExist(propertyPath)));
return false;
}
if (patchProperty.Property.Ignored)
{
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatCannotUpdateProperty(propertyPath)));
return false;
}
return true;
}
private bool IsNonStringArray(Type type)
@ -840,25 +909,6 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
return (!(type == typeof(string)) && typeof(IList).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()));
}
private bool CheckIfPropertyCanBeSet(
ConversionResult result,
object objectToApplyTo,
Operation operation,
string path)
{
if (!result.CanBeConverted)
{
LogError(new JsonPatchError(
objectToApplyTo,
operation,
Resources.FormatInvalidValueForProperty(result.ConvertedInstance, path)));
return false;
}
return true;
}
private void LogError(JsonPatchError jsonPatchError)
{
if (LogErrorAction != null)
@ -871,54 +921,6 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
}
}
private JsonPatchProperty FindPropertyAndParent(object targetObject, string propertyPath)
{
try
{
var splitPath = propertyPath.Split('/');
// skip the first one if it's empty
var startIndex = (string.IsNullOrWhiteSpace(splitPath[0]) ? 1 : 0);
for (int i = startIndex; i < splitPath.Length; i++)
{
var jsonContract = (JsonObjectContract)ContractResolver.ResolveContract(targetObject.GetType());
foreach (var property in jsonContract.Properties)
{
if (string.Equals(property.PropertyName, splitPath[i], StringComparison.OrdinalIgnoreCase))
{
if (i == (splitPath.Length - 1))
{
return new JsonPatchProperty(property, targetObject);
}
else
{
targetObject = property.ValueProvider.GetValue(targetObject);
// if property is of IList type then get the array index from splitPath and get the
// object at the indexed position from the list.
if (GetIListType(property.PropertyType) != null)
{
var index = int.Parse(splitPath[++i]);
targetObject = ((IList)targetObject)[index];
}
}
break;
}
}
}
return null;
}
catch (Exception)
{
// will result in JsonPatchException in calling class, as expected
return null;
}
}
private ConversionResult ConvertToActualType(Type propertyType, object value)
{
try
@ -962,20 +964,6 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
return false;
}
private int GetNumericEnd(string path)
{
var possibleIndex = path.Substring(path.LastIndexOf("/") + 1);
var castedIndex = -1;
if (int.TryParse(possibleIndex, out castedIndex))
{
return castedIndex;
}
return -1;
}
private ActualPropertyPathResult GetActualPropertyPath(
[NotNull] string propertyPath,
[NotNull] object objectToApplyTo,

View File

@ -0,0 +1,30 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.JsonPatch.Helpers
{
/// <summary>
/// Return value for the helper method used by Copy/Move. Needed to ensure we can make a different
/// decision in the calling method when the value is null because it cannot be fetched (HasError = true)
/// versus when it actually is null (much like why RemovedPropertyTypeResult is used for returning
/// type in the Remove operation).
/// </summary>
public class GetValueResult
{
public GetValueResult(object propertyValue, bool hasError)
{
PropertyValue = propertyValue;
HasError = hasError;
}
/// <summary>
/// The value of the property we're trying to get
/// </summary>
public object PropertyValue { get; private set; }
/// <summary>
/// HasError: true when an error occurred, the operation didn't complete succesfully
/// </summary>
public bool HasError { get; private set; }
}
}

View File

@ -0,0 +1,245 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Dynamic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
{
public class CopyOperationTests
{
[Fact]
public void Copy()
{
dynamic doc = new ExpandoObject();
doc.StringProperty = "A";
doc.AnotherStringProperty = "B";
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("StringProperty", "AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.AnotherStringProperty);
}
[Fact]
public void CopyInList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerList/0", "IntegerList/1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.IntegerList);
}
[Fact]
public void CopyFromListToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerList/0", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.IntegerList);
}
[Fact]
public void CopyFromListToNonList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerList/0", "IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.IntegerValue);
}
[Fact]
public void CopyFromNonListToList()
{
dynamic doc = new ExpandoObject();
doc.IntegerValue = 5;
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerValue", "IntegerList/0");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
}
[Fact]
public void CopyToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.IntegerValue = 5;
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerValue", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
}
[Fact]
public void NestedCopy()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
{
StringProperty = "A",
AnotherStringProperty = "B"
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
}
[Fact]
public void NestedCopyInList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
}
[Fact]
public void NestedCopyFromListToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList);
}
[Fact]
public void NestedCopyFromListToNonList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.SimpleDTO.IntegerValue);
}
[Fact]
public void NestedCopyFromNonListToList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
}
[Fact]
public void NestedCopyToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList);
}
}
}

View File

@ -0,0 +1,268 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
{
public class CopyTypedOperationTests
{
[Fact]
public void Copy()
{
var doc = new SimpleDTO()
{
StringProperty = "A",
AnotherStringProperty = "B"
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("StringProperty", "AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.AnotherStringProperty);
}
[Fact]
public void CopyInList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerList/0", "IntegerList/1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.IntegerList);
}
[Fact]
public void CopyFromListToEndOfList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerList/0", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.IntegerList);
}
[Fact]
public void CopyFromListToNonList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerList/0", "IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.IntegerValue);
}
[Fact]
public void CopyFromNonListToList()
{
var doc = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerValue", "IntegerList/0");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
}
[Fact]
public void CopyToEndOfList()
{
var doc = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("IntegerValue", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
}
[Fact]
public void NestedCopy()
{
var doc = new SimpleDTOWithNestedDTO()
{
SimpleDTO = new SimpleDTO()
{
StringProperty = "A",
AnotherStringProperty = "B"
}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
}
[Fact]
public void NestedCopyInList()
{
var doc = new SimpleDTOWithNestedDTO()
{
SimpleDTO = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
}
[Fact]
public void NestedCopyFromListToEndOfList()
{
var doc = new SimpleDTOWithNestedDTO()
{
SimpleDTO = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList);
}
[Fact]
public void NestedCopyFromListToNonList()
{
var doc = new SimpleDTOWithNestedDTO()
{
SimpleDTO = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.SimpleDTO.IntegerValue);
}
[Fact]
public void NestedCopyFromNonListToList()
{
var doc = new SimpleDTOWithNestedDTO()
{
SimpleDTO = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
}
[Fact]
public void NestedCopyToEndOfList()
{
var doc = new SimpleDTOWithNestedDTO()
{
SimpleDTO = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList);
}
}
}

View File

@ -0,0 +1,338 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Dynamic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
{
public class MoveOperationTests
{
[Fact]
public void Move()
{
dynamic doc = new ExpandoObject();
doc.StringProperty = "A";
doc.AnotherStringProperty = "B";
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("StringProperty", "AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.AnotherStringProperty);
var cont = doc as IDictionary<string, object>;
object valueFromDictionary;
cont.TryGetValue("StringProperty", out valueFromDictionary);
Assert.Null(valueFromDictionary);
}
[Fact]
public void MoveToNonExisting()
{
dynamic doc = new ExpandoObject();
doc.StringProperty = "A";
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("StringProperty", "AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.AnotherStringProperty);
var cont = doc as IDictionary<string, object>;
object valueFromDictionary;
cont.TryGetValue("StringProperty", out valueFromDictionary);
Assert.Null(valueFromDictionary);
}
[Fact]
public void MoveDynamicToTyped()
{
dynamic doc = new ExpandoObject();
doc.StringProperty = "A";
doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("StringProperty", "SimpleDTO/AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
var cont = doc as IDictionary<string, object>;
object valueFromDictionary;
cont.TryGetValue("StringProperty", out valueFromDictionary);
Assert.Null(valueFromDictionary);
}
[Fact]
public void MoveTypedToDynamic()
{
dynamic doc = new ExpandoObject();
doc.StringProperty = "A";
doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("SimpleDTO/AnotherStringProperty", "StringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("B", doc.StringProperty);
Assert.Equal(null, doc.SimpleDTO.AnotherStringProperty);
}
[Fact]
public void NestedMove()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
{
StringProperty = "A",
AnotherStringProperty = "B"
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("Nested/StringProperty", "Nested/AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.Nested.AnotherStringProperty);
Assert.Equal(null, doc.Nested.StringProperty);
}
[Fact]
public void MoveInList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerList/0", "IntegerList/1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 1, 3 }, doc.IntegerList);
}
[Fact]
public void NestedMoveInList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 1, 3 }, doc.Nested.IntegerList);
}
[Fact]
public void MoveFromListToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerList/0", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 3, 1 }, doc.IntegerList);
}
[Fact]
public void NestedMoveFromListToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 3, 1 }, doc.Nested.IntegerList);
}
[Fact]
public void MoveFomListToNonList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerList/0", "IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 3 }, doc.IntegerList);
Assert.Equal(1, doc.IntegerValue);
}
[Fact]
public void NestedMoveFomListToNonList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 3 }, doc.Nested.IntegerList);
Assert.Equal(1, doc.Nested.IntegerValue);
}
[Fact]
public void MoveFromNonListToList()
{
dynamic doc = new ExpandoObject();
doc.IntegerValue = 5;
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerValue", "IntegerList/0");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
var cont = doc as IDictionary<string, object>;
object valueFromDictionary;
cont.TryGetValue("IntegerValue", out valueFromDictionary);
Assert.Null(valueFromDictionary);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
}
[Fact]
public void NestedMoveFromNonListToList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/0");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(0, doc.Nested.IntegerValue);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.Nested.IntegerList);
}
[Fact]
public void MoveToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.IntegerValue = 5;
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerValue", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
var cont = doc as IDictionary<string, object>;
object valueFromDictionary;
cont.TryGetValue("IntegerValue", out valueFromDictionary);
Assert.Null(valueFromDictionary);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
}
[Fact]
public void NestedMoveToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(0, doc.Nested.IntegerValue);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.Nested.IntegerList);
}
}
}

View File

@ -0,0 +1,138 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
{
public class MoveTypedOperationTests
{
[Fact]
public void Move()
{
var doc = new SimpleDTO()
{
StringProperty = "A",
AnotherStringProperty = "B"
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("StringProperty", "AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.AnotherStringProperty);
Assert.Equal(null, doc.StringProperty);
}
[Fact]
public void MoveInList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerList/0", "IntegerList/1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 1, 3 }, doc.IntegerList);
}
[Fact]
public void MoveFromListToEndOfList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerList/0", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 3, 1 }, doc.IntegerList);
}
[Fact]
public void MoveFomListToNonList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerList/0", "IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 2, 3 }, doc.IntegerList);
Assert.Equal(1, doc.IntegerValue);
}
[Fact]
public void MoveFromNonListToList()
{
var doc = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerValue", "IntegerList/0");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(0, doc.IntegerValue);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
}
[Fact]
public void MoveToEndOfList()
{
var doc = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Move("IntegerValue", "IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(0, doc.IntegerValue);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
}
}
}

View File

@ -0,0 +1,242 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
{
public class ReplaceOperationTests
{
[Fact]
public void ReplaceGuidTest()
{
dynamic doc = new SimpleDTO()
{
GuidValue = Guid.NewGuid()
};
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("GuidValue", newGuid);
// serialize & deserialize
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserizalized.ApplyTo(doc);
Assert.Equal(newGuid, doc.GuidValue);
}
[Fact]
public void ReplaceGuidTestExpandoObject()
{
dynamic doc = new ExpandoObject();
doc.GuidValue = Guid.NewGuid();
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("GuidValue", newGuid);
// serialize & deserialize
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserizalized.ApplyTo(doc);
Assert.Equal(newGuid, doc.GuidValue);
}
[Fact]
public void ReplaceGuidTestExpandoObjectInAnonymous()
{
dynamic nestedObject = new ExpandoObject();
nestedObject.GuidValue = Guid.NewGuid();
dynamic doc = new
{
NestedObject = nestedObject
};
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("nestedobject/GuidValue", newGuid);
// serialize & deserialize
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserizalized.ApplyTo(doc);
Assert.Equal(newGuid, doc.NestedObject.GuidValue);
}
[Fact]
public void ReplaceNestedObjectTest()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
var newDTO = new SimpleDTO()
{
DoubleValue = 1
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTO", newDTO);
// serialize & deserialize
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.SimpleDTO.DoubleValue);
Assert.Equal(0, doc.SimpleDTO.IntegerValue);
Assert.Equal(null, doc.SimpleDTO.IntegerList);
}
[Fact]
public void ReplaceInList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/0", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 5, 2, 3 }, doc.IntegerList);
}
[Fact]
public void ReplaceFullList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
}
[Fact]
public void ReplaceInListInList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTOList = new List<SimpleDTO>() {
new SimpleDTO() {
IntegerList = new List<int>(){1,2,3}
}};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[0]);
}
[Fact]
public void ReplaceInListInListAtEnd()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTOList = new List<SimpleDTO>() {
new SimpleDTO() {
IntegerList = new List<int>(){1,2,3}
}};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTOList/0/IntegerList/-", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[2]);
}
[Fact]
public void ReplaceFullListFromEnumerable()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
}
[Fact]
public void ReplaceFullListWithCollection()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new Collection<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
}
[Fact]
public void ReplaceAtEndOfList()
{
dynamic doc = new ExpandoObject();
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/-", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 5 }, doc.IntegerList);
}
}
}

View File

@ -0,0 +1,191 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
{
public class ReplaceTypedOperationTests
{
[Fact]
public void ReplaceGuidTest()
{
var doc = new SimpleDTO()
{
GuidValue = Guid.NewGuid()
};
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("GuidValue", newGuid);
// serialize & deserialize
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserizalized.ApplyTo(doc);
Assert.Equal(newGuid, doc.GuidValue);
}
[Fact]
public void SerializeAndReplaceNestedObjectTest()
{
var doc = new SimpleDTOWithNestedDTO()
{
SimpleDTO = new SimpleDTO()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
}
};
var newDTO = new SimpleDTO()
{
DoubleValue = 1
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTO", newDTO);
// serialize & deserialize
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.SimpleDTO.DoubleValue);
Assert.Equal(0, doc.SimpleDTO.IntegerValue);
Assert.Equal(null, doc.SimpleDTO.IntegerList);
}
[Fact]
public void ReplaceInList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/0", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 5, 2, 3 }, doc.IntegerList);
}
[Fact]
public void ReplaceFullList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
}
[Fact]
public void ReplaceInListInList()
{
var doc = new SimpleDTO()
{
SimpleDTOList = new List<SimpleDTO>() {
new SimpleDTO() {
IntegerList = new List<int>(){1,2,3}
}}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(4, doc.SimpleDTOList.First().IntegerList.First());
}
[Fact]
public void ReplaceFullListFromEnumerable()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
}
[Fact]
public void ReplaceFullListWithCollection()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new Collection<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
}
[Fact]
public void ReplaceAtEndOfList()
{
var doc = new SimpleDTO()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/-", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2, 5 }, doc.IntegerList);
}
}
}