Support DynamicObject types (#99)

Addresses #38
This commit is contained in:
Jass Bagga 2017-08-24 15:11:01 -07:00 committed by GitHub
parent d4b64af0e6
commit 3d6a8615de
41 changed files with 1950 additions and 1208 deletions

View File

@ -0,0 +1,211 @@
// 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.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.CSharp.RuntimeBinder;
using Newtonsoft.Json.Serialization;
using CSharpBinder = Microsoft.CSharp.RuntimeBinder;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class DynamicObjectAdapter : IAdapter
{
public bool TryAdd(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
if (!TrySetDynamicObjectProperty(target, contractResolver, segment, value, out errorMessage))
{
return false;
}
errorMessage = null;
return true;
}
public bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out value, out errorMessage))
{
value = null;
return false;
}
errorMessage = null;
return true;
}
public bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage))
{
return false;
}
// Setting the value to "null" will use the default value in case of value types, and
// null in case of reference types
object value = null;
if (property.GetType().GetTypeInfo().IsValueType
&& Nullable.GetUnderlyingType(property.GetType()) == null)
{
value = Activator.CreateInstance(property.GetType());
}
if (!TrySetDynamicObjectProperty(target, contractResolver, segment, value, out errorMessage))
{
return false;
}
errorMessage = null;
return true;
}
public bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage))
{
return false;
}
if (!TryConvertValue(value, property.GetType(), out var convertedValue))
{
errorMessage = Resources.FormatInvalidValueForProperty(value);
return false;
}
if (!TrySetDynamicObjectProperty(target, contractResolver, segment, convertedValue, out errorMessage))
{
return false;
}
errorMessage = null;
return true;
}
public bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
out object nextTarget,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage))
{
nextTarget = null;
return false;
}
else
{
nextTarget = property;
errorMessage = null;
return true;
}
}
private bool TryGetDynamicObjectProperty(
object target,
IContractResolver contractResolver,
string segment,
out object value,
out string errorMessage)
{
var jsonDynamicContract = (JsonDynamicContract)contractResolver.ResolveContract(target.GetType());
var propertyName = jsonDynamicContract.PropertyNameResolver(segment);
var binder = CSharpBinder.Binder.GetMember(
CSharpBinderFlags.None,
propertyName,
target.GetType(),
new List<CSharpArgumentInfo>
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
});
var callsite = CallSite<Func<CallSite, object, object>>.Create(binder);
try
{
value = callsite.Target(callsite, target);
errorMessage = null;
return true;
}
catch (RuntimeBinderException)
{
value = null;
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
}
private bool TrySetDynamicObjectProperty(
object target,
IContractResolver contractResolver,
string segment,
object value,
out string errorMessage)
{
var jsonDynamicContract = (JsonDynamicContract)contractResolver.ResolveContract(target.GetType());
var propertyName = jsonDynamicContract.PropertyNameResolver(segment);
var binder = CSharpBinder.Binder.SetMember(
CSharpBinderFlags.None,
propertyName,
target.GetType(),
new List<CSharpArgumentInfo>
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
});
var callsite = CallSite<Func<CallSite, object, object, object>>.Create(binder);
try
{
callsite.Target(callsite, target, value);
errorMessage = null;
return true;
}
catch (RuntimeBinderException)
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
}
private bool TryConvertValue(object value, Type propertyType, out object convertedValue)
{
var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType);
if (!conversionResult.CanBeConverted)
{
convertedValue = null;
return false;
}
convertedValue = conversionResult.ConvertedInstance;
return true;
}
}
}

View File

@ -15,13 +15,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
public ObjectVisitor(ParsedPath path, IContractResolver contractResolver)
{
if (contractResolver == null)
{
throw new ArgumentNullException(nameof(contractResolver));
}
_path = path;
_contractResolver = contractResolver;
_contractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver));
}
public bool TryVisit(ref object target, out IAdapter adapter, out string errorMessage)
@ -38,8 +33,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
// Traverse until the penultimate segment to get the target object and adapter
for (var i = 0; i < _path.Segments.Count - 1; i++)
{
object next;
if (!adapter.TryTraverse(target, _path.Segments[i], _contractResolver, out next, out errorMessage))
if (!adapter.TryTraverse(target, _path.Segments[i], _contractResolver, out var next, out errorMessage))
{
adapter = null;
return false;
@ -59,6 +53,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
{
return new ExpandoObjectAdapter();
}
else if (targetObject is IDynamicMetaObjectProvider)
{
return new DynamicObjectAdapter();
}
else if (targetObject is IDictionary)
{
return new DictionaryAdapter();

View File

@ -10,277 +10,243 @@ namespace Microsoft.AspNetCore.JsonPatch
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.AspNetCore.JsonPatch.Resources", typeof(Resources).GetTypeInfo().Assembly);
/// <summary>
/// The type of the property at path '{0}' could not be determined.
/// </summary>
internal static string CannotDeterminePropertyType
{
get { return GetString("CannotDeterminePropertyType"); }
}
/// <summary>
/// The type of the property at path '{0}' could not be determined.
/// </summary>
internal static string FormatCannotDeterminePropertyType(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0);
}
/// <summary>
/// The property at '{0}' could not be copied.
/// </summary>
internal static string CannotCannotCopyProperty
internal static string CannotCopyProperty
{
get { return GetString("CannotCannotCopyProperty"); }
get => GetString("CannotCopyProperty");
}
/// <summary>
/// The property at '{0}' could not be copied.
/// </summary>
internal static string FormatCannotCopyProperty(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("CannotCopyProperty"), p0);
/// <summary>
/// The type of the property at path '{0}' could not be determined.
/// </summary>
internal static string CannotDeterminePropertyType
{
return string.Format(CultureInfo.CurrentCulture, GetString("CannotCannotCopyProperty"), p0);
get => GetString("CannotDeterminePropertyType");
}
/// <summary>
/// The type of the property at path '{0}' could not be determined.
/// </summary>
internal static string FormatCannotDeterminePropertyType(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0);
/// <summary>
/// The '{0}' operation at path '{1}' could not be performed.
/// </summary>
internal static string CannotPerformOperation
{
get { return GetString("CannotPerformOperation"); }
get => GetString("CannotPerformOperation");
}
/// <summary>
/// The '{0}' operation at path '{1}' could not be performed.
/// </summary>
internal static string FormatCannotPerformOperation(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("CannotPerformOperation"), p0, p1);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("CannotPerformOperation"), p0, p1);
/// <summary>
/// The property at '{0}' could not be read.
/// </summary>
internal static string CannotReadProperty
{
get { return GetString("CannotReadProperty"); }
get => GetString("CannotReadProperty");
}
/// <summary>
/// The property at '{0}' could not be read.
/// </summary>
internal static string FormatCannotReadProperty(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("CannotReadProperty"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("CannotReadProperty"), p0);
/// <summary>
/// The property at path '{0}' could not be updated.
/// </summary>
internal static string CannotUpdateProperty
{
get { return GetString("CannotUpdateProperty"); }
get => GetString("CannotUpdateProperty");
}
/// <summary>
/// The property at path '{0}' could not be updated.
/// </summary>
internal static string FormatCannotUpdateProperty(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0);
/// <summary>
/// The index value provided by path segment '{0}' is out of bounds of the array size.
/// </summary>
internal static string IndexOutOfBounds
{
get { return GetString("IndexOutOfBounds"); }
get => GetString("IndexOutOfBounds");
}
/// <summary>
/// The index value provided by path segment '{0}' is out of bounds of the array size.
/// </summary>
internal static string FormatIndexOutOfBounds(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("IndexOutOfBounds"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("IndexOutOfBounds"), p0);
/// <summary>
/// The path segment '{0}' is invalid for an array index.
/// </summary>
internal static string InvalidIndexValue
{
get { return GetString("InvalidIndexValue"); }
get => GetString("InvalidIndexValue");
}
/// <summary>
/// The path segment '{0}' is invalid for an array index.
/// </summary>
internal static string FormatInvalidIndexValue(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexValue"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexValue"), p0);
/// <summary>
/// The type '{0}' was malformed and could not be parsed.
/// </summary>
internal static string InvalidJsonPatchDocument
{
get { return GetString("InvalidJsonPatchDocument"); }
get => GetString("InvalidJsonPatchDocument");
}
/// <summary>
/// The type '{0}' was malformed and could not be parsed.
/// </summary>
internal static string FormatInvalidJsonPatchDocument(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0);
/// <summary>
/// Invalid JsonPatch operation '{0}'.
/// </summary>
internal static string InvalidJsonPatchOperation
{
get { return GetString("InvalidJsonPatchOperation"); }
get => GetString("InvalidJsonPatchOperation");
}
/// <summary>
/// Invalid JsonPatch operation '{0}'.
/// </summary>
internal static string FormatInvalidJsonPatchOperation(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchOperation"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchOperation"), p0);
/// <summary>
/// The provided string '{0}' is an invalid path.
/// </summary>
internal static string InvalidValueForPath
{
get { return GetString("InvalidValueForPath"); }
get => GetString("InvalidValueForPath");
}
/// <summary>
/// The provided string '{0}' is an invalid path.
/// </summary>
internal static string FormatInvalidValueForPath(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForPath"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForPath"), p0);
/// <summary>
/// The value '{0}' is invalid for target location.
/// </summary>
internal static string InvalidValueForProperty
{
get { return GetString("InvalidValueForProperty"); }
get => GetString("InvalidValueForProperty");
}
/// <summary>
/// The value '{0}' is invalid for target location.
/// </summary>
internal static string FormatInvalidValueForProperty(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0);
/// <summary>
/// '{0}' must be of type '{1}'.
/// </summary>
internal static string ParameterMustMatchType
{
get { return GetString("ParameterMustMatchType"); }
get => GetString("ParameterMustMatchType");
}
/// <summary>
/// '{0}' must be of type '{1}'.
/// </summary>
internal static string FormatParameterMustMatchType(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ParameterMustMatchType"), p0, p1);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("ParameterMustMatchType"), p0, p1);
/// <summary>
/// The type '{0}' which is an array is not supported for json patch operations as it has a fixed size.
/// </summary>
internal static string PatchNotSupportedForArrays
{
get { return GetString("PatchNotSupportedForArrays"); }
get => GetString("PatchNotSupportedForArrays");
}
/// <summary>
/// The type '{0}' which is an array is not supported for json patch operations as it has a fixed size.
/// </summary>
internal static string FormatPatchNotSupportedForArrays(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForArrays"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForArrays"), p0);
/// <summary>
/// The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported.
/// </summary>
internal static string PatchNotSupportedForNonGenericLists
{
get { return GetString("PatchNotSupportedForNonGenericLists"); }
get => GetString("PatchNotSupportedForNonGenericLists");
}
/// <summary>
/// The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported.
/// </summary>
internal static string FormatPatchNotSupportedForNonGenericLists(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForNonGenericLists"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForNonGenericLists"), p0);
/// <summary>
/// The target location specified by path segment '{0}' was not found.
/// </summary>
internal static string TargetLocationAtPathSegmentNotFound
{
get { return GetString("TargetLocationAtPathSegmentNotFound"); }
get => GetString("TargetLocationAtPathSegmentNotFound");
}
/// <summary>
/// The target location specified by path segment '{0}' was not found.
/// </summary>
internal static string FormatTargetLocationAtPathSegmentNotFound(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationAtPathSegmentNotFound"), p0);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationAtPathSegmentNotFound"), p0);
/// <summary>
/// For operation '{0}', the target location specified by path '{1}' was not found.
/// </summary>
internal static string TargetLocationNotFound
{
get { return GetString("TargetLocationNotFound"); }
get => GetString("TargetLocationNotFound");
}
/// <summary>
/// For operation '{0}', the target location specified by path '{1}' was not found.
/// </summary>
internal static string FormatTargetLocationNotFound(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationNotFound"), p0, p1);
}
=> string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationNotFound"), p0, p1);
/// <summary>
/// The test operation is not supported.
/// </summary>
internal static string TestOperationNotSupported
{
get { return GetString("TestOperationNotSupported"); }
get => GetString("TestOperationNotSupported");
}
/// <summary>
/// The test operation is not supported.
/// </summary>
internal static string FormatTestOperationNotSupported()
{
return GetString("TestOperationNotSupported");
}
=> GetString("TestOperationNotSupported");
private static string GetString(string name, params string[] formatterNames)
{

View File

@ -20,10 +20,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
dictionary[nameKey] = "Mike";
var dictionaryAdapter = new DictionaryAdapter();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
string message = null;
// Act
var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message);
var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message);
// Assert
Assert.True(addStatus);
@ -38,12 +37,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
// Arrange
var dictionaryAdapter = new DictionaryAdapter();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
string message = null;
var nameKey = "Name";
var dictionary = new Dictionary<string, object>(StringComparer.Ordinal);
// Act
var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message);
var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message);
// Assert
Assert.True(addStatus);
@ -52,8 +50,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
Assert.Equal("James", dictionary[nameKey]);
// Act
object outValue = null;
addStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver.Object, out outValue, out message);
addStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver.Object, out var outValue, out message);
// Assert
Assert.True(addStatus);
@ -67,12 +64,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
// Arrange
var dictionaryAdapter = new DictionaryAdapter();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
string message = null;
var nameKey = "Name";
var dictionary = new Dictionary<string, object>(StringComparer.Ordinal);
// Act
var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message);
var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message);
// Assert
Assert.True(addStatus);
@ -81,8 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
Assert.Equal("James", dictionary[nameKey]);
// Act
object outValue = null;
addStatus = dictionaryAdapter.TryGet(dictionary, nameKey, resolver.Object, out outValue, out message);
addStatus = dictionaryAdapter.TryGet(dictionary, nameKey, resolver.Object, out var outValue, out message);
// Assert
Assert.True(addStatus);
@ -99,10 +94,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
dictionary.Add(nameKey, "Mike");
var dictionaryAdapter = new DictionaryAdapter();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
string message = null;
// Act
var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "James", out message);
var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "James", out var message);
// Assert
Assert.True(replaceStatus);
@ -119,10 +113,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var dictionary = new Dictionary<string, object>(StringComparer.Ordinal);
var dictionaryAdapter = new DictionaryAdapter();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
string message = null;
// Act
var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "Mike", out message);
var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "Mike", out var message);
// Assert
Assert.False(replaceStatus);
@ -140,10 +133,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var dictionary = new Dictionary<string, object>(StringComparer.Ordinal);
var dictionaryAdapter = new DictionaryAdapter();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
string message = null;
// Act
var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out message);
var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out var message);
// Assert
Assert.False(removeStatus);
@ -162,10 +154,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
dictionary[nameKey] = "James";
var dictionaryAdapter = new DictionaryAdapter();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
string message = null;
// Act
var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out message);
var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out var message);
//Assert
Assert.True(removeStatus);

View File

@ -8,7 +8,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class AddOperationTests
{
@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
dynamic doc = new
{
Test = 1,
nested = new NestedDTO()
nested = new NestedObject()
};
// create patch
@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
dynamic doc = new
{
Test = 1,
nested = new NestedDTO()
nested = new NestedObject()
};
// create patch
@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void AddNewPropertyToExpandoOjectInTypedObject()
{
var doc = new NestedDTO()
var doc = new NestedObject()
{
DynamicProperty = new ExpandoObject()
};
@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
dynamic dynamicProperty = new ExpandoObject();
dynamicProperty.StringProperty = "A";
var doc = new NestedDTO()
var doc = new NestedObject()
{
DynamicProperty = dynamicProperty
};
@ -284,7 +284,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void AddResultsShouldReplaceInNestedInDynamic()
{
dynamic doc = new ExpandoObject();
doc.Nested = new NestedDTO();
doc.Nested = new NestedObject();
doc.Nested.DynamicProperty = new ExpandoObject();
doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject();
doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject();
@ -319,7 +319,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// the root of the document, nor a member of an existing object, nor a
// member of an existing array.
var doc = new NestedDTO()
var doc = new NestedObject()
{
DynamicProperty = new ExpandoObject()
};

View File

@ -6,14 +6,14 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class AddTypedOperationTests
{
[Fact]
public void AddToListNegativePosition()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -37,11 +37,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void AddToListInList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
ListOfSimpleDTO = new List<SimpleDTO>()
ListOfSimpleObject = new List<SimpleObject>()
{
new SimpleDTO()
new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -50,23 +50,23 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Add("ListOfSimpleDTO/0/IntegerList/0", 4);
patchDoc.Add("ListOfSimpleObject/0/IntegerList/0", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.ListOfSimpleDTO[0].IntegerList);
Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.ListOfSimpleObject[0].IntegerList);
}
[Fact]
public void AddToListInListInvalidPositionTooSmall()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
ListOfSimpleDTO = new List<SimpleDTO>()
ListOfSimpleObject = new List<SimpleObject>()
{
new SimpleDTO()
new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Add("ListOfSimpleDTO/-1/IntegerList/0", 4);
patchDoc.Add("ListOfSimpleObject/-1/IntegerList/0", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
@ -92,11 +92,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void AddToListInListInvalidPositionTooLarge()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
ListOfSimpleDTO = new List<SimpleDTO>()
ListOfSimpleObject = new List<SimpleObject>()
{
new SimpleDTO()
new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
};
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4);
patchDoc.Add("ListOfSimpleObject/20/IntegerList/0", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

View File

@ -6,7 +6,7 @@ using System.Dynamic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class CopyOperationTests
{
@ -122,7 +122,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedCopy()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleObject = new SimpleObject()
{
StringProperty = "A",
AnotherStringProperty = "B"
@ -130,82 +130,82 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty");
patchDoc.Copy("SimpleObject/StringProperty", "SimpleObject/AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
Assert.Equal("A", doc.SimpleObject.AnotherStringProperty);
}
[Fact]
public void NestedCopyInList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1");
patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/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);
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList);
}
[Fact]
public void NestedCopyFromListToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-");
patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/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);
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList);
}
[Fact]
public void NestedCopyFromListToNonList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue");
patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.SimpleDTO.IntegerValue);
Assert.Equal(1, doc.SimpleObject.IntegerValue);
}
[Fact]
public void NestedCopyFromNonListToList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleObject = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -213,19 +213,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0");
patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/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);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList);
}
[Fact]
public void NestedCopyToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleObject = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -233,13 +233,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-");
patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/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);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList);
}
}
}

View File

@ -5,14 +5,14 @@ using System.Collections.Generic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class CopyTypedOperationTests
{
[Fact]
public void Copy()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
StringProperty = "A",
AnotherStringProperty = "B"
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void CopyInList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void CopyFromListToEndOfList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void CopyFromListToNonList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void CopyFromNonListToList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void CopyToEndOfList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -132,9 +132,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void NestedCopy()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
StringProperty = "A",
AnotherStringProperty = "B"
@ -143,22 +143,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty");
patchDoc.Copy("SimpleObject/StringProperty", "SimpleObject/AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
Assert.Equal("A", doc.SimpleObject.AnotherStringProperty);
}
[Fact]
public void NestedCopyInList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -166,21 +166,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1");
patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/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);
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList);
}
[Fact]
public void NestedCopyFromListToEndOfList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -188,22 +188,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-");
patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/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);
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList);
}
[Fact]
public void NestedCopyFromListToNonList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -211,21 +211,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue");
patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerValue");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.SimpleDTO.IntegerValue);
Assert.Equal(1, doc.SimpleObject.IntegerValue);
}
[Fact]
public void NestedCopyFromNonListToList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -234,20 +234,20 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0");
patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/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);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList);
}
[Fact]
public void NestedCopyToEndOfList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -256,13 +256,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-");
patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/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);
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList);
}
}
}

View File

@ -0,0 +1,10 @@
// 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.AspNetCore.JsonPatch.Internal
{
public class InheritedObject : SimpleObject
{
public string AdditionalStringProperty { get; set; }
}
}

View File

@ -6,7 +6,7 @@ using System.Dynamic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class MoveOperationTests
{
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
Assert.Equal("A", doc.AnotherStringProperty);
var cont = doc as IDictionary<string, object>;
cont.TryGetValue("StringProperty", out var valueFromDictionary);
cont.TryGetValue("StringProperty", out object valueFromDictionary);
Assert.Null(valueFromDictionary);
}
@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
{
dynamic doc = new ExpandoObject();
doc.StringProperty = "A";
doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" };
doc.SimpleDTO = new SimpleObject() { AnotherStringProperty = "B" };
// create patch
var patchDoc = new JsonPatchDocument();
@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
var cont = doc as IDictionary<string, object>;
cont.TryGetValue("StringProperty", out var valueFromDictionary);
cont.TryGetValue("StringProperty", out object valueFromDictionary);
Assert.Null(valueFromDictionary);
}
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
{
dynamic doc = new ExpandoObject();
doc.StringProperty = "A";
doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" };
doc.SimpleDTO = new SimpleObject() { AnotherStringProperty = "B" };
// create patch
var patchDoc = new JsonPatchDocument();
@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedMove()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
doc.Nested = new SimpleObject()
{
StringProperty = "A",
AnotherStringProperty = "B"
@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedMoveInList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
doc.Nested = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -181,7 +181,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedMoveFromListToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
doc.Nested = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -220,7 +220,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedMoveFomListToNonList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
doc.Nested = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -255,7 +255,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
deserialized.ApplyTo(doc);
var cont = doc as IDictionary<string, object>;
cont.TryGetValue("IntegerValue", out var valueFromDictionary);
cont.TryGetValue("IntegerValue", out object valueFromDictionary);
Assert.Null(valueFromDictionary);
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
@ -265,7 +265,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedMoveFromNonListToList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
doc.Nested = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -311,7 +311,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedMoveToEndOfList()
{
dynamic doc = new ExpandoObject();
doc.Nested = new SimpleDTO()
doc.Nested = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }

View File

@ -5,14 +5,14 @@ using System.Collections.Generic;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class MoveTypedOperationTests
{
[Fact]
public void Move()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
StringProperty = "A",
AnotherStringProperty = "B"
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void MoveInList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void MoveFromListToEndOfList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void MoveFomListToNonList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void MoveFromNonListToList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void MoveToEndOfList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }

View File

@ -1,9 +1,9 @@
// 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.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class NestedDTO
public class NestedObject
{
public string StringProperty { get; set; }
public dynamic DynamicProperty { get; set; }

View File

@ -5,7 +5,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class PatchDocumentTests
{
@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void NonGenericPatchDocToGenericMustSerialize()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
StringProperty = "A",
AnotherStringProperty = "B"
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
patchDoc.Copy("StringProperty", "AnotherStringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleDTO>>(serialized);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleObject>>(serialized);
deserialized.ApplyTo(doc);
@ -71,14 +71,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void GenericPatchDocToNonGenericMustSerialize()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
StringProperty = "A",
AnotherStringProperty = "B"
};
var patchDocTyped = new JsonPatchDocument<SimpleDTO>();
patchDocTyped.Copy<string>(o => o.StringProperty, o => o.AnotherStringProperty);
var patchDocTyped = new JsonPatchDocument<SimpleObject>();
patchDocTyped.Copy(o => o.StringProperty, o => o.AnotherStringProperty);
var patchDocUntyped = new JsonPatchDocument();
patchDocUntyped.Copy("StringProperty", "AnotherStringProperty");

View File

@ -7,7 +7,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class RemoveOperationTests
{
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
deserialized.ApplyTo(obj);
var cont = obj as IDictionary<string, object>;
cont.TryGetValue("Test", out var valueFromDictionary);
cont.TryGetValue("Test", out object valueFromDictionary);
Assert.Null(valueFromDictionary);
}
@ -94,9 +94,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
{
deserialized.ApplyTo(obj);
});
Assert.Equal(
string.Format("The target location specified by path segment '{0}' was not found.",
"test"),
string.Format(
"The target location specified by path segment '{0}' was not found.",
"test"),
exception.Message);
}
@ -117,7 +119,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
deserialized.ApplyTo(obj);
var cont = obj as IDictionary<string, object>;
cont.TryGetValue("Test", out var valueFromDictionary);
cont.TryGetValue("Test", out object valueFromDictionary);
Assert.Null(valueFromDictionary);
}
@ -139,8 +141,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
{
deserialized.ApplyTo(obj);
});
Assert.Equal(
string.Format("The target location specified by path segment '{0}' was not found.", "test"),
string.Format(
"The target location specified by path segment '{0}' was not found.",
"test"),
exception.Message);
}
@ -148,7 +153,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedRemove()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleDTO = new SimpleObject()
{
StringProperty = "A"
};
@ -168,14 +173,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedRemove_MixedCase_ThrowsPathNotFoundException()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleObject = new SimpleObject()
{
StringProperty = "A"
};
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("Simpledto/stringProperty");
patchDoc.Remove("Simpleobject/stringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
@ -184,10 +189,12 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
{
deserialized.ApplyTo(doc);
});
Assert.Equal(
string.Format("For operation '{0}', the target location specified by path '{1}' was not found.",
"remove",
"/Simpledto/stringProperty"),
string.Format(
"For operation '{0}', the target location specified by path '{1}' was not found.",
"remove",
"/Simpleobject/stringProperty"),
exception.Message);
}
@ -195,7 +202,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedRemoveFromList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleDTO = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -213,10 +220,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
}
[Fact]
public void NestedRemoveFromListMixedCase()
public void NestedRemoveFromList_MixedCase()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleDTO = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -237,7 +244,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedRemoveFromListInvalidPositionTooLarge()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleDTO = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -262,7 +269,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedRemoveFromListInvalidPositionTooSmall()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleDTO = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -287,7 +294,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void NestedRemoveFromEndOfList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleDTO = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};

View File

@ -6,14 +6,14 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class RemoveTypedOperationTests
{
[Fact]
public void Remove()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
StringProperty = "A"
};
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void RemoveFromList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void RemoveFromListInvalidPositionTooLarge()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void RemoveFromListInvalidPositionTooSmall()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void RemoveFromEndOfList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
@ -121,9 +121,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void NestedRemove()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
StringProperty = "A"
}
@ -131,22 +131,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("SimpleDTO/StringProperty");
patchDoc.Remove("SimpleObject/StringProperty");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Null(doc.SimpleDTO.StringProperty);
Assert.Null(doc.SimpleObject.StringProperty);
}
[Fact]
public void NestedRemoveFromList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -154,22 +154,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("SimpleDTO/IntegerList/2");
patchDoc.Remove("SimpleObject/IntegerList/2");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleDTO.IntegerList);
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleObject.IntegerList);
}
[Fact]
public void NestedRemoveFromListInvalidPositionTooLarge()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -177,7 +177,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("SimpleDTO/IntegerList/3");
patchDoc.Remove("SimpleObject/IntegerList/3");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
@ -194,9 +194,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void NestedRemoveFromListInvalidPositionTooSmall()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -204,7 +204,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("SimpleDTO/IntegerList/-1");
patchDoc.Remove("SimpleObject/IntegerList/-1");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
@ -221,9 +221,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void NestedRemoveFromEndOfList()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
}
@ -231,14 +231,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
// create patch
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("SimpleDTO/IntegerList/-");
patchDoc.Remove("SimpleObject/IntegerList/-");
var serialized = JsonConvert.SerializeObject(patchDoc);
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
deserialized.ApplyTo(doc);
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleDTO.IntegerList);
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleObject.IntegerList);
}
}
}

View File

@ -9,21 +9,21 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class ReplaceOperationTests
{
[Fact]
public void ReplaceGuidTest()
{
dynamic doc = new SimpleDTO()
dynamic doc = new SimpleObject()
{
GuidValue = Guid.NewGuid()
};
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("GuidValue", newGuid);
// serialize & deserialize
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("GuidValue", newGuid);
// serialize & deserialize
@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("nestedobject/GuidValue", newGuid);
// serialize & deserialize
@ -84,19 +84,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void ReplaceNestedObjectTest()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTO = new SimpleDTO()
doc.SimpleDTO = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
var newDTO = new SimpleDTO()
var newDTO = new SimpleObject()
{
DoubleValue = 1
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTO", newDTO);
// serialize & deserialize
@ -117,7 +117,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/0", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -150,13 +150,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void ReplaceInListInList()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTOList = new List<SimpleDTO>() {
new SimpleDTO() {
doc.SimpleDTOList = new List<SimpleObject>() {
new SimpleObject() {
IntegerList = new List<int>(){1,2,3}
}};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -171,13 +171,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
public void ReplaceInListInListAtEnd()
{
dynamic doc = new ExpandoObject();
doc.SimpleDTOList = new List<SimpleDTO>() {
new SimpleDTO() {
doc.SimpleDTOList = new List<SimpleObject>() {
new SimpleObject() {
IntegerList = new List<int>(){1,2,3}
}};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTOList/0/IntegerList/-", 4);
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -195,7 +195,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -213,7 +213,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new Collection<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -231,7 +231,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
doc.IntegerList = new List<int>() { 1, 2, 3 };
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/-", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);

View File

@ -8,21 +8,21 @@ using System.Linq;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class ReplaceTypedOperationTests
{
[Fact]
public void ReplaceGuidTest()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
GuidValue = Guid.NewGuid()
};
var newGuid = Guid.NewGuid();
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("GuidValue", newGuid);
// serialize & deserialize
@ -37,23 +37,23 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void SerializeAndReplaceNestedObjectTest()
{
var doc = new SimpleDTOWithNestedDTO()
var doc = new SimpleObjectWithNestedObject()
{
SimpleDTO = new SimpleDTO()
SimpleObject = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
}
};
var newDTO = new SimpleDTO()
var newDTO = new SimpleObject()
{
DoubleValue = 1
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTO", newDTO);
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleObject", newDTO);
// serialize & deserialize
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -61,21 +61,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
deserialized.ApplyTo(doc);
Assert.Equal(1, doc.SimpleDTO.DoubleValue);
Assert.Equal(0, doc.SimpleDTO.IntegerValue);
Assert.Null(doc.SimpleDTO.IntegerList);
Assert.Equal(1, doc.SimpleObject.DoubleValue);
Assert.Equal(0, doc.SimpleObject.IntegerValue);
Assert.Null(doc.SimpleObject.IntegerList);
}
[Fact]
public void ReplaceInList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/0", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -89,13 +89,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void ReplaceFullList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -109,36 +109,36 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void ReplaceInListInList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
SimpleDTOList = new List<SimpleDTO>() {
new SimpleDTO() {
SimpleObjectList = new List<SimpleObject>() {
new SimpleObject() {
IntegerList = new List<int>(){1,2,3}
}}
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4);
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleObjectList/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());
Assert.Equal(4, doc.SimpleObjectList.First().IntegerList.First());
}
[Fact]
public void ReplaceFullListFromEnumerable()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -152,13 +152,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void ReplaceFullListWithCollection()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new Collection<int>() { 4, 5, 6 });
var serialized = JsonConvert.SerializeObject(patchDoc);
@ -172,13 +172,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
[Fact]
public void ReplaceAtEndOfList()
{
var doc = new SimpleDTO()
var doc = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
// create patch
JsonPatchDocument patchDoc = new JsonPatchDocument();
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList/-", 5);
var serialized = JsonConvert.SerializeObject(patchDoc);

View File

@ -1,22 +0,0 @@
// 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;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
{
public class SimpleDTOWithNestedDTO
{
public int IntegerValue { get; set; }
public NestedDTO NestedDTO { get; set; }
public SimpleDTO SimpleDTO { get; set; }
public List<SimpleDTO> ListOfSimpleDTO { get; set; }
public SimpleDTOWithNestedDTO()
{
NestedDTO = new NestedDTO();
SimpleDTO = new SimpleDTO();
ListOfSimpleDTO = new List<SimpleDTO>();
}
}
}

View File

@ -4,11 +4,11 @@
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class SimpleDTO
public class SimpleObject
{
public List<SimpleDTO> SimpleDTOList { get; set; }
public List<SimpleObject> SimpleObjectList { get; set; }
public List<int> IntegerList { get; set; }
public int IntegerValue { get; set; }
public string StringProperty { get; set; }

View File

@ -0,0 +1,22 @@
// 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;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class SimpleObjectWithNestedObject
{
public int IntegerValue { get; set; }
public NestedObject NestedObject { get; set; }
public SimpleObject SimpleObject { get; set; }
public List<SimpleObject> ListOfSimpleObject { get; set; }
public SimpleObjectWithNestedObject()
{
NestedObject = new NestedObject();
SimpleObject = new SimpleObject();
ListOfSimpleObject = new List<SimpleObject>();
}
}
}

View File

@ -0,0 +1,231 @@
// 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.Serialization;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class DynamicObjectAdapterTest
{
[Fact]
public void TryAdd_AddsNewProperty()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act
var status = adapter.TryAdd(target, segment, resolver, "new", out string errorMessage);
// Assert
Assert.True(status);
Assert.Null(errorMessage);
Assert.Equal("new", target.NewProperty);
}
[Fact]
public void TryAdd_ReplacesExistingPropertyValue()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
target.List = new List<int>() { 1, 2, 3 };
var value = new List<string>() { "stringValue1", "stringValue2" };
var segment = "List";
var resolver = new DefaultContractResolver();
// Act
var status = adapter.TryAdd(target, segment, resolver, value, out string errorMessage);
// Assert
Assert.True(status);
Assert.Null(errorMessage);
Assert.Equal(value, target.List);
}
[Fact]
public void TryGet_GetsPropertyValue_ForExistingProperty()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act 1
var addStatus = adapter.TryAdd(target, segment, resolver, "new", out string errorMessage);
// Assert 1
Assert.True(addStatus);
Assert.Null(errorMessage);
Assert.Equal("new", target.NewProperty);
// Act 2
var getStatus = adapter.TryGet(target, segment, resolver, out object getValue, out string getErrorMessage);
// Assert 2
Assert.True(getStatus);
Assert.Null(getErrorMessage);
Assert.Equal(getValue, target.NewProperty);
}
[Fact]
public void TryGet_ThrowsPathNotFoundException_ForNonExistingProperty()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act
var getStatus = adapter.TryGet(target, segment, resolver, out object getValue, out string getErrorMessage);
// Assert
Assert.False(getStatus);
Assert.Null(getValue);
Assert.Equal($"The target location specified by path segment '{segment}' was not found.", getErrorMessage);
}
[Fact]
public void TryTraverse_FindsNextTarget()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
target.NestedObject = new DynamicTestObject();
target.NestedObject.NewProperty = "A";
var segment = "NestedObject";
var resolver = new DefaultContractResolver();
// Act
var status = adapter.TryTraverse(target, segment, resolver, out object nextTarget, out string errorMessage);
// Assert
Assert.True(status);
Assert.Null(errorMessage);
Assert.Equal(target.NestedObject, nextTarget);
}
[Fact]
public void TryTraverse_ThrowsPathNotFoundException_ForNonExistingProperty()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
target.NestedObject = new DynamicTestObject();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act
var status = adapter.TryTraverse(target.NestedObject, segment, resolver, out object nextTarget, out string errorMessage);
// Assert
Assert.False(status);
Assert.Equal($"The target location specified by path segment '{segment}' was not found.", errorMessage);
}
[Fact]
public void TryReplace_ReplacesPropertyValue()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
target.NewProperty = new object();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act
var status = adapter.TryReplace(target, segment, resolver, "new", out string errorMessage);
// Assert
Assert.True(status);
Assert.Null(errorMessage);
Assert.Equal("new", target.NewProperty);
}
[Fact]
public void TryReplace_ThrowsPathNotFoundException_ForNonExistingProperty()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act
var status = adapter.TryReplace(target, segment, resolver, "test", out string errorMessage);
// Assert
Assert.False(status);
Assert.Equal($"The target location specified by path segment '{segment}' was not found.", errorMessage);
}
[Fact]
public void TryReplace_ThrowsPropertyInvalidException_IfNewValueIsNotTheSameTypeAsInitialValue()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
target.NewProperty = 1;
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act
var status = adapter.TryReplace(target, segment, resolver, "test", out string errorMessage);
// Assert
Assert.False(status);
Assert.Equal($"The value 'test' is invalid for target location.", errorMessage);
}
[Theory]
[InlineData(1, 0)]
[InlineData("new", null)]
public void TryRemove_SetsPropertyToDefaultOrNull(object value, object expectedValue)
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act 1
var addStatus = adapter.TryAdd(target, segment, resolver, value, out string errorMessage);
// Assert 1
Assert.True(addStatus);
Assert.Null(errorMessage);
Assert.Equal(value, target.NewProperty);
// Act 2
var removeStatus = adapter.TryRemove(target, segment, resolver, out string removeErrorMessage);
// Assert 2
Assert.True(removeStatus);
Assert.Null(removeErrorMessage);
Assert.Equal(expectedValue, target.NewProperty);
}
[Fact]
public void TryRemove_ThrowsPathNotFoundException_ForNonExistingProperty()
{
// Arrange
var adapter = new DynamicObjectAdapter();
dynamic target = new DynamicTestObject();
var segment = "NewProperty";
var resolver = new DefaultContractResolver();
// Act
var removeStatus = adapter.TryRemove(target, segment, resolver, out string removeErrorMessage);
// Assert
Assert.False(removeStatus);
Assert.Equal($"The target location specified by path segment '{segment}' was not found.", removeErrorMessage);
}
}
}

View File

@ -0,0 +1,87 @@
// 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;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class DynamicTestObject : DynamicObject
{
private Dictionary<string, object> _dictionary = new Dictionary<string, object>();
public object this[string key] { get => ((IDictionary<string, object>)_dictionary)[key]; set => ((IDictionary<string, object>)_dictionary)[key] = value; }
public ICollection<string> Keys => ((IDictionary<string, object>)_dictionary).Keys;
public ICollection<object> Values => ((IDictionary<string, object>)_dictionary).Values;
public int Count => ((IDictionary<string, object>)_dictionary).Count;
public bool IsReadOnly => ((IDictionary<string, object>)_dictionary).IsReadOnly;
public void Add(string key, object value)
{
((IDictionary<string, object>)_dictionary).Add(key, value);
}
public void Add(KeyValuePair<string, object> item)
{
((IDictionary<string, object>)_dictionary).Add(item);
}
public void Clear()
{
((IDictionary<string, object>)_dictionary).Clear();
}
public bool Contains(KeyValuePair<string, object> item)
{
return ((IDictionary<string, object>)_dictionary).Contains(item);
}
public bool ContainsKey(string key)
{
return ((IDictionary<string, object>)_dictionary).ContainsKey(key);
}
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
((IDictionary<string, object>)_dictionary).CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return ((IDictionary<string, object>)_dictionary).GetEnumerator();
}
public bool Remove(string key)
{
return ((IDictionary<string, object>)_dictionary).Remove(key);
}
public bool Remove(KeyValuePair<string, object> item)
{
return ((IDictionary<string, object>)_dictionary).Remove(item);
}
public bool TryGetValue(string key, out object value)
{
return ((IDictionary<string, object>)_dictionary).TryGetValue(key, out value);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var name = binder.Name;
return TryGetValue(name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_dictionary[binder.Name] = value;
return true;
}
}
}

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNetCore.JsonPatch
{
public class InheritedDTO : SimpleDTO
public class InheritedObject : SimpleObject
{
public string AdditionalStringProperty { get; set; }
}

View File

@ -0,0 +1,263 @@
// 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 Microsoft.AspNetCore.JsonPatch.Exceptions;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class DynamicObjectIntegrationTests
{
[Fact]
public void AddResults_ShouldReplaceExistingPropertyValue_InNestedDynamicObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.Nested = new NestedObject();
dynamicTestObject.Nested.DynamicProperty = new DynamicTestObject();
dynamicTestObject.Nested.DynamicProperty.InBetweenFirst = new DynamicTestObject();
dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new DynamicTestObject();
dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A";
var patchDoc = new JsonPatchDocument();
patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B");
// Act
patchDoc.ApplyTo(dynamicTestObject);
// Assert
Assert.Equal("B", dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty);
}
[Fact]
public void ShouldNotBeAbleToAdd_ToNonExistingProperty_ThatIsNotTheRoot()
{
//Adding to a Nonexistent Target
//
// An example target JSON document:
// { "foo": "bar" }
// A JSON Patch document:
// [
// { "op": "add", "path": "/baz/bat", "value": "qux" }
// ]
// This JSON Patch document, applied to the target JSON document above,
// would result in an error (therefore, it would not be applied),
// because the "add" operation's target location that references neither
// the root of the document, nor a member of an existing object, nor a
// member of an existing array.
// Arrange
var nestedObject = new NestedObject()
{
DynamicProperty = new DynamicTestObject()
};
var patchDoc = new JsonPatchDocument();
patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1);
// Act
var exception = Assert.Throws<JsonPatchException>(() =>
{
patchDoc.ApplyTo(nestedObject);
});
// Assert
Assert.Equal(
string.Format(
"The target location specified by path segment '{0}' was not found.",
"OtherProperty"),
exception.Message);
}
[Fact]
public void CopyProperties_InNestedDynamicObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.NestedDynamicObject = new DynamicTestObject();
dynamicTestObject.NestedDynamicObject.StringProperty = "A";
dynamicTestObject.NestedDynamicObject.AnotherStringProperty = "B";
var patchDoc = new JsonPatchDocument();
patchDoc.Copy("NestedDynamicObject/StringProperty", "NestedDynamicObject/AnotherStringProperty");
// Act
patchDoc.ApplyTo(dynamicTestObject);
// Assert
Assert.Equal("A", dynamicTestObject.NestedDynamicObject.AnotherStringProperty);
}
[Fact]
public void MoveToNonExistingProperty_InDynamicObject_ShouldAddNewProperty()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.StringProperty = "A";
var patchDoc = new JsonPatchDocument();
patchDoc.Move("StringProperty", "AnotherStringProperty");
// Act
patchDoc.ApplyTo(dynamicTestObject);
dynamicTestObject.TryGetValue("StringProperty", out object valueFromDictionary);
// Assert
Assert.Equal("A", dynamicTestObject.AnotherStringProperty);
Assert.Null(valueFromDictionary);
}
[Fact]
public void MovePropertyValue_FromDynamicObject_ToTypedObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.StringProperty = "A";
dynamicTestObject.SimpleObject = new SimpleObject() { AnotherStringProperty = "B" };
var patchDoc = new JsonPatchDocument();
patchDoc.Move("StringProperty", "SimpleObject/AnotherStringProperty");
// Act
patchDoc.ApplyTo(dynamicTestObject);
dynamicTestObject.TryGetValue("StringProperty", out object valueFromDictionary);
// Assert
Assert.Equal("A", dynamicTestObject.SimpleObject.AnotherStringProperty);
Assert.Null(valueFromDictionary);
}
[Fact]
public void MovePropertyValue_FromListToNonList_InNestedTypedObject_InDynamicObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.Nested = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
var patchDoc = new JsonPatchDocument();
patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue");
// Act
patchDoc.ApplyTo(dynamicTestObject);
// Assert
Assert.Equal(new List<int>() { 2, 3 }, dynamicTestObject.Nested.IntegerList);
Assert.Equal(1, dynamicTestObject.Nested.IntegerValue);
}
[Fact]
public void RemoveNestedProperty_FromDynamicObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.Test = new DynamicTestObject();
dynamicTestObject.Test.AnotherTest = "A";
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("Test");
// Act
patchDoc.ApplyTo(dynamicTestObject);
dynamicTestObject.TryGetValue("Test", out object valueFromDictionary);
// Assert
Assert.Null(valueFromDictionary);
}
[Fact]
public void RemoveFromNestedObject_InDynamicObject_MixedCase_ThrowsPathNotFoundException()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.SimpleObject = new SimpleObject()
{
StringProperty = "A"
};
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("Simpleobject/stringProperty");
// Act
var exception = Assert.Throws<JsonPatchException>(() =>
{
patchDoc.ApplyTo(dynamicTestObject);
});
// Assert
Assert.Equal(
string.Format("The target location specified by path segment '{0}' was not found.",
"Simpleobject"),
exception.Message);
}
[Fact]
public void RemoveFromList_NestedInDynamicObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.SimpleObject = new SimpleObject()
{
IntegerList = new List<int>() { 1, 2, 3 }
};
var patchDoc = new JsonPatchDocument();
patchDoc.Remove("SimpleObject/IntegerList/2");
// Act
patchDoc.ApplyTo(dynamicTestObject);
// Assert
Assert.Equal(new List<int>() { 1, 2 }, dynamicTestObject.SimpleObject.IntegerList);
}
[Fact]
public void ReplaceNestedTypedObject_InDynamicObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.SimpleObject = new SimpleObject()
{
IntegerValue = 5,
IntegerList = new List<int>() { 1, 2, 3 }
};
var newObject = new SimpleObject()
{
DoubleValue = 1
};
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("SimpleObject", newObject);
// Act
patchDoc.ApplyTo(dynamicTestObject);
// Assert
Assert.Equal(1, dynamicTestObject.SimpleObject.DoubleValue);
Assert.Equal(0, dynamicTestObject.SimpleObject.IntegerValue);
Assert.Null(dynamicTestObject.SimpleObject.IntegerList);
}
[Fact]
public void ReplaceFullList_InDynamicObject()
{
// Arrange
dynamic dynamicTestObject = new DynamicTestObject();
dynamicTestObject.IntegerList = new List<int>() { 1, 2, 3 };
var patchDoc = new JsonPatchDocument();
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
// Act
patchDoc.ApplyTo(dynamicTestObject);
// Assert
Assert.Equal(new List<int>() { 4, 5, 6 }, dynamicTestObject.IntegerList);
}
}
}

View File

@ -14,14 +14,14 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Add_WithExpression_RespectsJsonPropertyName_ForModelProperty()
{
var patchDoc = new JsonPatchDocument<JsonPropertyDTO>();
var patchDoc = new JsonPatchDocument<JsonPropertyObject>();
patchDoc.Add(p => p.Name, "John");
var serialized = JsonConvert.SerializeObject(patchDoc);
// serialized value should have "AnotherName" as path
// deserialize to a JsonPatchDocument<JsonPropertyWithAnotherNameDTO> to check
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithAnotherNameDTO>>(serialized);
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithAnotherNameObject>>(serialized);
// get path
var pathToCheck = deserialized.Operations.First().path;
@ -65,19 +65,19 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToDifferentlyTypedClassWithPropertyMatchingJsonPropertyName()
{
var patchDocToSerialize = new JsonPatchDocument<JsonPropertyDTO>();
var patchDocToSerialize = new JsonPatchDocument<JsonPropertyObject>();
patchDocToSerialize.Add(p => p.Name, "John");
// the patchdoc will deserialize to "anothername". We should thus be able to apply
// it to a class that HAS that other property name.
var doc = new JsonPropertyWithAnotherNameDTO()
var doc = new JsonPropertyWithAnotherNameObject()
{
AnotherName = "InitialValue"
};
var serialized = JsonConvert.SerializeObject(patchDocToSerialize);
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithAnotherNameDTO>>
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithAnotherNameObject>>
(serialized);
deserialized.ApplyTo(doc);
@ -88,21 +88,21 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToSameTypedClassWithMatchingJsonPropertyName()
{
var patchDocToSerialize = new JsonPatchDocument<JsonPropertyDTO>();
var patchDocToSerialize = new JsonPatchDocument<JsonPropertyObject>();
patchDocToSerialize.Add(p => p.Name, "John");
// the patchdoc will deserialize to "anothername". As JsonPropertyDTO has
// a JsonProperty signifying that "Name" should be deseriallized from "AnotherName",
// we should be able to apply the patchDoc.
var doc = new JsonPropertyDTO()
var doc = new JsonPropertyObject()
{
Name = "InitialValue"
};
var serialized = JsonConvert.SerializeObject(patchDocToSerialize);
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyDTO>>
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyObject>>
(serialized);
deserialized.ApplyTo(doc);
@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Add_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument()
{
var doc = new JsonPropertyDTO()
var doc = new JsonPropertyObject()
{
Name = "InitialValue"
};
@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.JsonPatch
// serialization should serialize to "AnotherName"
var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]";
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyDTO>>(serialized);
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyObject>>(serialized);
deserialized.ApplyTo(doc);
@ -131,7 +131,7 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Remove_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument()
{
var doc = new JsonPropertyDTO()
var doc = new JsonPropertyObject()
{
Name = "InitialValue"
};
@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.JsonPatch
// serialization should serialize to "AnotherName"
var serialized = "[{\"path\":\"/AnotherName\",\"op\":\"remove\"}]";
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyDTO>>(serialized);
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyObject>>(serialized);
deserialized.ApplyTo(doc);
@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Add_OnApplyFromJson_RespectsInheritedJsonPropertyNameOnJsonDocument()
{
var doc = new JsonPropertyWithInheritanceDTO()
var doc = new JsonPropertyWithInheritanceObject()
{
Name = "InitialName"
};
@ -157,7 +157,7 @@ namespace Microsoft.AspNetCore.JsonPatch
// serialization should serialize to "AnotherName"
var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]";
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithInheritanceDTO>>(serialized);
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithInheritanceObject>>(serialized);
deserialized.ApplyTo(doc);
@ -167,14 +167,14 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Add_WithExpression_RespectsJsonPropertyName_ForInheritedModelProperty()
{
var patchDoc = new JsonPatchDocument<JsonPropertyWithInheritanceDTO>();
var patchDoc = new JsonPatchDocument<JsonPropertyWithInheritanceObject>();
patchDoc.Add(p => p.Name, "John");
var serialized = JsonConvert.SerializeObject(patchDoc);
// serialized value should have "AnotherName" as path
// deserialize to a JsonPatchDocument<JsonPropertyWithAnotherNameDTO> to check
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithAnotherNameDTO>>(serialized);
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyWithAnotherNameObject>>(serialized);
// get path
var pathToCheck = deserialized.Operations.First().path;
@ -184,10 +184,10 @@ namespace Microsoft.AspNetCore.JsonPatch
[Fact]
public void Add_OnApplyFromJson_EscapingHandledOnComplexJsonPropertyNameOnJsonDocument()
{
var doc = new JsonPropertyComplexNameDTO()
var doc = new JsonPropertyComplexNameObject()
{
FooSlashBars = "InitialName",
FooSlashTilde = new SimpleDTO
FooSlashTilde = new SimpleObject
{
StringProperty = "Initial Value"
}
@ -196,7 +196,7 @@ namespace Microsoft.AspNetCore.JsonPatch
// serialization should serialize to "AnotherName"
var serialized = "[{\"value\":\"Kevin\",\"path\":\"/foo~1bar~0\",\"op\":\"add\"},{\"value\":\"Final Value\",\"path\":\"/foo~1~0/StringProperty\",\"op\":\"replace\"}]";
var deserialized =
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyComplexNameDTO>>(serialized);
JsonConvert.DeserializeObject<JsonPatchDocument<JsonPropertyComplexNameObject>>(serialized);
deserialized.ApplyTo(doc);

View File

@ -5,12 +5,12 @@ using Newtonsoft.Json;
namespace Microsoft.AspNetCore.JsonPatch
{
public class JsonPropertyComplexNameDTO
public class JsonPropertyComplexNameObject
{
[JsonProperty("foo/bar~")]
public string FooSlashBars { get; set; }
[JsonProperty("foo/~")]
public SimpleDTO FooSlashTilde { get; set; }
public SimpleObject FooSlashTilde { get; set; }
}
}

View File

@ -5,7 +5,7 @@ using Newtonsoft.Json;
namespace Microsoft.AspNetCore.JsonPatch
{
public class JsonPropertyDTO
public class JsonPropertyObject
{
[JsonProperty("AnotherName")]
public string Name { get; set; }

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNetCore.JsonPatch
{
public class JsonPropertyWithAnotherNameDTO
public class JsonPropertyWithAnotherNameObject
{
public string AnotherName { get; set; }
}

View File

@ -1,19 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.JsonPatch
{
public class JsonPropertyWithInheritanceDTO : JsonPropertyWithInheritanceBaseDTO
{
public override string Name { get; set; }
}
public abstract class JsonPropertyWithInheritanceBaseDTO
{
[JsonProperty("AnotherName")]
public abstract string Name { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using Newtonsoft.Json;
namespace Microsoft.AspNetCore.JsonPatch
{
public class JsonPropertyWithInheritanceObject : JsonPropertyWithInheritanceBaseObject
{
public override string Name { get; set; }
}
public abstract class JsonPropertyWithInheritanceBaseObject
{
[JsonProperty("AnotherName")]
public abstract string Name { get; set; }
}
}

View File

@ -18,10 +18,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new[] { 20, 30 };
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, "0", resolver.Object, "40", out message);
var addStatus = listAdapter.TryAdd(targetObject, "0", resolver.Object, "40", out var message);
// Assert
Assert.False(addStatus);
@ -41,10 +40,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
targetObject.Add(20);
targetObject.Add(30);
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "40", out message);
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "40", out var message);
// Assert
Assert.False(addStatus);
@ -62,11 +60,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<string>() { "James", "Mike" };
var listAdapter = new ListAdapter();
string message = null;
var position = targetObject.Count.ToString();
// Act
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "Rob", out message);
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "Rob", out var message);
// Assert
Assert.Null(message);
@ -85,10 +82,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<string>() { "James", "Mike" };
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out message);
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out var message);
// Assert
Assert.False(addStatus);
@ -106,10 +102,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<string>() { "James", "Mike" };
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out message);
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out var message);
// Assert
Assert.False(addStatus);
@ -143,10 +138,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
// Arrange
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "20", out message);
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "20", out var message);
// Assert
Assert.True(addStatus);
@ -162,10 +156,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var listAdapter = new ListAdapter();
var targetObject = new List<string>() { "James", "Mike" };
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, value: null, errorMessage: out message);
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, value: null, errorMessage: out var message);
// Assert
Assert.True(addStatus);
@ -178,21 +171,20 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
public void Add_CompatibleTypeWorks()
{
// Arrange
var sDto = new SimpleDTO();
var iDto = new InheritedDTO();
var sDto = new SimpleObject();
var iDto = new InheritedObject();
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<SimpleDTO>() { sDto };
var targetObject = new List<SimpleObject>() { sDto };
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, iDto, out message);
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, iDto, out var message);
// Assert
Assert.True(addStatus);
Assert.True(string.IsNullOrEmpty(message), "Expected no error message");
Assert.Equal(2, targetObject.Count);
Assert.Equal(new List<SimpleDTO>() { sDto, iDto }, targetObject);
Assert.Equal(new List<SimpleObject>() { sDto, iDto }, targetObject);
}
[Fact]
@ -202,10 +194,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>() { 10, 20 };
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "James", out message);
var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "James", out var message);
// Assert
Assert.False(addStatus);
@ -253,10 +244,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
// Arrange
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out message);
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out var message);
// Assert
Assert.True(addStatus);
@ -267,34 +257,34 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
public static TheoryData<IList, object, string, IList> AddingKeepsObjectReferenceData {
get {
var sDto1 = new SimpleDTO();
var sDto2 = new SimpleDTO();
var sDto3 = new SimpleDTO();
var sDto1 = new SimpleObject();
var sDto2 = new SimpleObject();
var sDto3 = new SimpleObject();
return new TheoryData<IList, object, string, IList>()
{
{
new List<SimpleDTO>() { },
new List<SimpleObject>() { },
sDto1,
"-",
new List<SimpleDTO>() { sDto1 }
new List<SimpleObject>() { sDto1 }
},
{
new List<SimpleDTO>() { sDto1, sDto2 },
new List<SimpleObject>() { sDto1, sDto2 },
sDto3,
"-",
new List<SimpleDTO>() { sDto1, sDto2, sDto3 }
new List<SimpleObject>() { sDto1, sDto2, sDto3 }
},
{
new List<SimpleDTO>() { sDto1, sDto2 },
new List<SimpleObject>() { sDto1, sDto2 },
sDto3,
"0",
new List<SimpleDTO>() { sDto3, sDto1, sDto2 }
new List<SimpleObject>() { sDto3, sDto1, sDto2 }
},
{
new List<SimpleDTO>() { sDto1, sDto2 },
new List<SimpleObject>() { sDto1, sDto2 },
sDto3,
"1",
new List<SimpleDTO>() { sDto1, sDto3, sDto2 }
new List<SimpleObject>() { sDto1, sDto3, sDto2 }
}
};
}
@ -307,10 +297,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
// Arrange
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var listAdapter = new ListAdapter();
string message = null;
// Act
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out message);
var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out var message);
// Assert
Assert.True(addStatus);
@ -329,11 +318,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>(input);
var listAdapter = new ListAdapter();
string message = null;
object value = null;
// Act
var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out value, out message);
var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out var value, out var message);
// Assert
Assert.False(getStatus);
@ -352,11 +339,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>(input);
var listAdapter = new ListAdapter();
string message = null;
object value = null;
// Act
var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out value, out message);
var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out var value, out var message);
// Assert
Assert.True(getStatus);
@ -374,10 +359,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>(input);
var listAdapter = new ListAdapter();
string message = null;
// Act
var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out message);
var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out var message);
// Assert
Assert.False(removeStatus);
@ -396,10 +380,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>(input);
var listAdapter = new ListAdapter();
string message = null;
// Act
var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out message);
var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out var message);
// Assert
Assert.True(removeStatus);
@ -413,10 +396,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>() { 10, 20 };
var listAdapter = new ListAdapter();
string message = null;
// Act
var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "James", out message);
var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "James", out var message);
// Assert
Assert.False(replaceStatus);
@ -432,10 +414,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>() { 10, 20 };
var listAdapter = new ListAdapter();
string message = null;
// Act
var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "30", out message);
var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "30", out var message);
// Assert
Assert.True(replaceStatus);
@ -469,10 +450,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var resolver = new Mock<IContractResolver>(MockBehavior.Strict);
var targetObject = new List<int>() { 10, 20 };
var listAdapter = new ListAdapter();
string message = null;
// Act
var replaceStatus = listAdapter.TryReplace(targetObject, position, resolver.Object, "30", out message);
var replaceStatus = listAdapter.TryReplace(targetObject, position, resolver.Object, "30", out var message);
// Assert
Assert.True(replaceStatus);

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNetCore.JsonPatch
{
public class NestedDTO
public class NestedObject
{
public string StringProperty { get; set; }
}

File diff suppressed because it is too large Load Diff

View File

@ -46,11 +46,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
{
// Arrange
var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver());
IAdapter adapter = null;
string message = null;
// Act
var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message);
var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message);
// Assert
Assert.True(visitStatus);
@ -81,11 +79,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
{
// Arrange
var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver());
IAdapter adapter = null;
string message = null;
// Act
var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message);
var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message);
// Assert
Assert.True(visitStatus);
@ -112,11 +108,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
{
// Arrange
var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver());
IAdapter adapter = null;
string message = null;
// Act
var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message);
var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message);
// Assert
Assert.True(visitStatus);
@ -146,11 +140,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
{
// Arrange
var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver());
IAdapter adapter = null;
string message = null;
// Act
var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message);
var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message);
// Assert
Assert.True(visitStatus);
@ -168,11 +160,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{position}/States/-"), new DefaultContractResolver());
var automobileDepartment = new Class1Nested();
object targetObject = automobileDepartment;
IAdapter adapter = null;
string message = null;
// Act
var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message);
var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message);
// Assert
Assert.False(visitStatus);
@ -190,11 +180,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{position}/States/-"), new DefaultContractResolver());
var automobileDepartment = new Class1Nested();
object targetObject = automobileDepartment;
IAdapter adapter = null;
string message = null;
// Act
var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message);
var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message);
// Assert
Assert.False(visitStatus);
@ -211,16 +199,30 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var visitor = new ObjectVisitor(new ParsedPath($"/NonExisting"), new DefaultContractResolver());
var model = new Class1();
object targetObject = model;
IAdapter adapter = null;
string message = null;
// Act
var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message);
var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message);
// Assert
Assert.True(visitStatus);
Assert.True(string.IsNullOrEmpty(message), "Expected no error message");
Assert.IsType<PocoAdapter>(adapter);
}
[Fact]
public void Visit_NullTarget_ReturnsNullAdapter()
{
// Arrange
var visitor = new ObjectVisitor(new ParsedPath("test"), new DefaultContractResolver());
// Act
object target = null;
var visitStatus = visitor.TryVisit(ref target, out var adapter, out var message);
// Assert
Assert.False(visitStatus);
Assert.Null(adapter);
Assert.Null(message);
}
}
}

View File

@ -1,30 +0,0 @@
// 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;
namespace Microsoft.AspNetCore.JsonPatch
{
public class SimpleDTOWithNestedDTO
{
public int IntegerValue { get; set; }
public NestedDTO NestedDTO { get; set; }
public SimpleDTO SimpleDTO { get; set; }
public InheritedDTO InheritedDTO { get; set; }
public List<SimpleDTO> SimpleDTOList { get; set; }
public IList<SimpleDTO> SimpleDTOIList { get; set; }
public SimpleDTOWithNestedDTO()
{
this.NestedDTO = new NestedDTO();
this.SimpleDTO = new SimpleDTO();
this.InheritedDTO = new InheritedDTO();
this.SimpleDTOList = new List<SimpleDTO>();
}
}
}

View File

@ -1,15 +0,0 @@
// 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.AspNetCore.JsonPatch
{
public class SimpleDTOWithNestedDTOWithNullCheck
{
public SimpleDTOWithNullCheck SimpleDTOWithNullCheck { get; set; }
public SimpleDTOWithNestedDTOWithNullCheck()
{
SimpleDTOWithNullCheck = new SimpleDTOWithNullCheck();
}
}
}

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.JsonPatch
{
public class SimpleDTO
public class SimpleObject
{
public List<int> IntegerList { get; set; }
public IList<int> IntegerIList { get; set; }

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.
using System.Collections.Generic;
namespace Microsoft.AspNetCore.JsonPatch
{
public class SimpleObjectWithNestedObject
{
public int IntegerValue { get; set; }
public NestedObject NestedObject { get; set; }
public SimpleObject SimpleObject { get; set; }
public InheritedObject InheritedObject { get; set; }
public List<SimpleObject> SimpleObjectList { get; set; }
public IList<SimpleObject> SimpleObjectIList { get; set; }
public SimpleObjectWithNestedObject()
{
NestedObject = new NestedObject();
SimpleObject = new SimpleObject();
InheritedObject = new InheritedObject();
SimpleObjectList = new List<SimpleObject>();
}
}
}

View File

@ -0,0 +1,15 @@
// 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.AspNetCore.JsonPatch
{
public class SimpleObjectWithNestedObjectWithNullCheck
{
public SimpleObjectWithNullCheck SimpleObjectWithNullCheck { get; set; }
public SimpleObjectWithNestedObjectWithNullCheck()
{
SimpleObjectWithNullCheck = new SimpleObjectWithNullCheck();
}
}
}

View File

@ -5,7 +5,7 @@ using System;
namespace Microsoft.AspNetCore.JsonPatch
{
public class SimpleDTOWithNullCheck
public class SimpleObjectWithNullCheck
{
private string stringProperty;