parent
d3f2b240d7
commit
e0ac69c9f7
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.JsonPatch", "src\Microsoft.AspNet.JsonPatch\Microsoft.AspNet.JsonPatch.xproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.JsonPatch.Test", "test\Microsoft.AspNet.JsonPatch.Test\Microsoft.AspNet.JsonPatch.Test.xproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{81C20848-E063-4E12-AC40-0B55A532C16C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{81C20848-E063-4E12-AC40-0B55A532C16C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{81C20848-E063-4E12-AC40-0B55A532C16C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{81C20848-E063-4E12-AC40-0B55A532C16C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{4D55F4D8-633B-462F-A5B1-FEB84BD2D534} = {430B59ED-F960-4D3A-8FFE-3370008E168D}
|
||||
{81C20848-E063-4E12-AC40-0B55A532C16C} = {36CD6341-AB44-44EB-B3AA-BF98C89FECDD}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Operations;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Adapters
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the operations that can be performed on a JSON patch document.
|
||||
/// </summary>
|
||||
public interface IObjectAdapter
|
||||
{
|
||||
void Add(Operation operation, object objectToApplyTo);
|
||||
void Copy(Operation operation, object objectToApplyTo);
|
||||
void Move(Operation operation, object objectToApplyTo);
|
||||
void Remove(Operation operation, object objectToApplyTo);
|
||||
void Replace(Operation operation, object objectToApplyTo);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,76 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Exceptions;
|
||||
using Microsoft.AspNet.JsonPatch.Operations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Converters
|
||||
{
|
||||
public class JsonPatchDocumentConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
|
||||
JsonSerializer serializer)
|
||||
{
|
||||
if (objectType != typeof(JsonPatchDocument))
|
||||
{
|
||||
throw new ArgumentException(Resources.FormatParameterMustMatchType("objectType", "JsonPatchDocument"), "objectType");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// load jObject
|
||||
var jObject = JArray.Load(reader);
|
||||
|
||||
// Create target object for Json => list of operations
|
||||
var targetOperations = new List<Operation>();
|
||||
|
||||
// Create a new reader for this jObject, and set all properties
|
||||
// to match the original reader.
|
||||
var jObjectReader = jObject.CreateReader();
|
||||
jObjectReader.Culture = reader.Culture;
|
||||
jObjectReader.DateParseHandling = reader.DateParseHandling;
|
||||
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
|
||||
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
|
||||
|
||||
// Populate the object properties
|
||||
serializer.Populate(jObjectReader, targetOperations);
|
||||
|
||||
// container target: the JsonPatchDocument.
|
||||
var container = new JsonPatchDocument(targetOperations, new DefaultContractResolver());
|
||||
|
||||
return container;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonPatchException(Resources.FormatInvalidJsonPatchDocument(objectType.Name), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value is IJsonPatchDocument)
|
||||
{
|
||||
var jsonPatchDoc = (IJsonPatchDocument)value;
|
||||
var lst = jsonPatchDoc.GetOperations();
|
||||
|
||||
// write out the operations, no envelope
|
||||
serializer.Serialize(writer, lst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Exceptions;
|
||||
using Microsoft.AspNet.JsonPatch.Operations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Converters
|
||||
{
|
||||
public class TypedJsonPatchDocumentConverter : JsonPatchDocumentConverter
|
||||
{
|
||||
public override object ReadJson(
|
||||
JsonReader reader,
|
||||
Type objectType,
|
||||
object existingValue,
|
||||
JsonSerializer serializer)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var genericType = objectType.GetGenericArguments()[0];
|
||||
|
||||
// load jObject
|
||||
var jObject = JArray.Load(reader);
|
||||
|
||||
// Create target object for Json => list of operations, typed to genericType
|
||||
var genericOperation = typeof(Operation<>);
|
||||
var concreteOperationType = genericOperation.MakeGenericType(genericType);
|
||||
|
||||
var genericList = typeof(List<>);
|
||||
var concreteList = genericList.MakeGenericType(concreteOperationType);
|
||||
|
||||
var targetOperations = Activator.CreateInstance(concreteList);
|
||||
|
||||
//Create a new reader for this jObject, and set all properties to match the original reader.
|
||||
var jObjectReader = jObject.CreateReader();
|
||||
jObjectReader.Culture = reader.Culture;
|
||||
jObjectReader.DateParseHandling = reader.DateParseHandling;
|
||||
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
|
||||
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
|
||||
|
||||
// Populate the object properties
|
||||
serializer.Populate(jObjectReader, targetOperations);
|
||||
|
||||
// container target: the typed JsonPatchDocument.
|
||||
var container = Activator.CreateInstance(objectType, targetOperations, new DefaultContractResolver());
|
||||
|
||||
return container;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonPatchException(Resources.FormatInvalidJsonPatchDocument(objectType.Name), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Operations;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Exceptions
|
||||
{
|
||||
public class JsonPatchException : Exception
|
||||
{
|
||||
public Operation FailedOperation { get; private set; }
|
||||
public object AffectedObject { get; private set; }
|
||||
|
||||
|
||||
public JsonPatchException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public JsonPatchException(JsonPatchError jsonPatchError, Exception innerException)
|
||||
: base(jsonPatchError.ErrorMessage, innerException)
|
||||
{
|
||||
FailedOperation = jsonPatchError.Operation;
|
||||
AffectedObject = jsonPatchError.AffectedObject;
|
||||
}
|
||||
|
||||
public JsonPatchException(JsonPatchError jsonPatchError)
|
||||
: this(jsonPatchError, null)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonPatchException(string message, Exception innerException)
|
||||
: base (message, innerException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
internal class ActualPropertyPathResult
|
||||
{
|
||||
public int NumericEnd { get; private set; }
|
||||
public string PathToProperty { get; set; }
|
||||
public bool ExecuteAtEnd { get; set; }
|
||||
|
||||
public ActualPropertyPathResult(
|
||||
int numericEnd,
|
||||
string pathToProperty,
|
||||
bool executeAtEnd)
|
||||
{
|
||||
NumericEnd = numericEnd;
|
||||
PathToProperty = pathToProperty;
|
||||
ExecuteAtEnd = executeAtEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
internal class ConversionResult
|
||||
{
|
||||
public bool CanBeConverted { get; private set; }
|
||||
public object ConvertedInstance { get; private set; }
|
||||
|
||||
public ConversionResult(bool canBeConverted, object convertedInstance)
|
||||
{
|
||||
CanBeConverted = canBeConverted;
|
||||
ConvertedInstance = convertedInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
// Helper methods to allow case-insensitive key search
|
||||
internal static class ExpandoObjectDictionaryExtensions
|
||||
{
|
||||
internal static void SetValueForCaseInsensitiveKey(
|
||||
this IDictionary<string, object> propertyDictionary,
|
||||
string key,
|
||||
object value)
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in propertyDictionary)
|
||||
{
|
||||
if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
propertyDictionary[kvp.Key] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void RemoveValueForCaseInsensitiveKey(
|
||||
this IDictionary<string, object> propertyDictionary,
|
||||
string key)
|
||||
{
|
||||
string realKey = null;
|
||||
foreach (KeyValuePair<string, object> kvp in propertyDictionary)
|
||||
{
|
||||
if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
realKey = kvp.Key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (realKey != null)
|
||||
{
|
||||
propertyDictionary.Remove(realKey);
|
||||
}
|
||||
}
|
||||
|
||||
internal static object GetValueForCaseInsensitiveKey(
|
||||
this IDictionary<string, object> propertyDictionary,
|
||||
string key)
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in propertyDictionary)
|
||||
{
|
||||
if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException(Resources.FormatDictionaryKeyNotFound(key));
|
||||
}
|
||||
|
||||
internal static bool ContainsCaseInsensitiveKey(
|
||||
this IDictionary<string, object> propertyDictionary,
|
||||
string key)
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in propertyDictionary)
|
||||
{
|
||||
if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// 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.Globalization;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
internal static class ExpressionHelpers
|
||||
{
|
||||
public static string GetPath<TModel, TProp>(Expression<Func<TModel, TProp>> expr) where TModel : class
|
||||
{
|
||||
return "/" + GetPath(expr.Body, true);
|
||||
}
|
||||
|
||||
private static string GetPath(Expression expr, bool firstTime)
|
||||
{
|
||||
switch (expr.NodeType)
|
||||
{
|
||||
case ExpressionType.ArrayIndex:
|
||||
var binaryExpression = (BinaryExpression)expr;
|
||||
|
||||
if (ContinueWithSubPath(binaryExpression.Left.NodeType, false))
|
||||
{
|
||||
var leftFromBinaryExpression = GetPath(binaryExpression.Left, false);
|
||||
return leftFromBinaryExpression + "/" + binaryExpression.Right.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return binaryExpression.Right.ToString();
|
||||
}
|
||||
case ExpressionType.Call:
|
||||
var methodCallExpression = (MethodCallExpression)expr;
|
||||
|
||||
if (ContinueWithSubPath(methodCallExpression.Object.NodeType, false))
|
||||
{
|
||||
var leftFromMemberCallExpression = GetPath(methodCallExpression.Object, false);
|
||||
return leftFromMemberCallExpression + "/" +
|
||||
GetIndexerInvocation(methodCallExpression.Arguments[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetIndexerInvocation(methodCallExpression.Arguments[0]);
|
||||
}
|
||||
case ExpressionType.Convert:
|
||||
return GetPath(((UnaryExpression)expr).Operand, false);
|
||||
case ExpressionType.MemberAccess:
|
||||
var memberExpression = expr as MemberExpression;
|
||||
|
||||
if (ContinueWithSubPath(memberExpression.Expression.NodeType, false))
|
||||
{
|
||||
var left = GetPath(memberExpression.Expression, false);
|
||||
return left + "/" + memberExpression.Member.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return memberExpression.Member.Name;
|
||||
}
|
||||
case ExpressionType.Parameter:
|
||||
// Fits "x => x" (the whole document which is "" as JSON pointer)
|
||||
return firstTime ? string.Empty : null;
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ContinueWithSubPath(ExpressionType expressionType, bool firstTime)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
return (expressionType == ExpressionType.ArrayIndex
|
||||
|| expressionType == ExpressionType.Call
|
||||
|| expressionType == ExpressionType.Convert
|
||||
|| expressionType == ExpressionType.MemberAccess
|
||||
|| expressionType == ExpressionType.Parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (expressionType == ExpressionType.ArrayIndex
|
||||
|| expressionType == ExpressionType.Call
|
||||
|| expressionType == ExpressionType.Convert
|
||||
|| expressionType == ExpressionType.MemberAccess);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetIndexerInvocation(Expression expression)
|
||||
{
|
||||
var converted = Expression.Convert(expression, typeof(object));
|
||||
var fakeParameter = Expression.Parameter(typeof(object), null);
|
||||
var lambda = Expression.Lambda<Func<object, object>>(converted, fakeParameter);
|
||||
Func<object, object> func;
|
||||
|
||||
func = lambda.Compile();
|
||||
|
||||
return Convert.ToString(func(null), CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Return value for the helper method used by Copy/Move. Needed to ensure we can make a different
|
||||
/// decision in the calling method when the value is null because it cannot be fetched (HasError = true)
|
||||
/// versus when it actually is null (much like why RemovedPropertyTypeResult is used for returning
|
||||
/// type in the Remove operation).
|
||||
/// </summary>
|
||||
public class GetValueResult
|
||||
{
|
||||
public GetValueResult(object propertyValue, bool hasError)
|
||||
{
|
||||
PropertyValue = propertyValue;
|
||||
HasError = hasError;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value of the property we're trying to get
|
||||
/// </summary>
|
||||
public object PropertyValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// HasError: true when an error occurred, the operation didn't complete succesfully
|
||||
/// </summary>
|
||||
public bool HasError { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// 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 Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata for JsonProperty.
|
||||
/// </summary>
|
||||
public class JsonPatchProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance.
|
||||
/// </summary>
|
||||
public JsonPatchProperty(JsonProperty property, object parent)
|
||||
{
|
||||
if (property == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(property));
|
||||
}
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parent));
|
||||
}
|
||||
|
||||
Property = property;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets JsonProperty.
|
||||
/// </summary>
|
||||
public JsonProperty Property { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets Parent.
|
||||
/// </summary>
|
||||
public object Parent { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
internal class ObjectTreeAnalysisResult
|
||||
{
|
||||
// either the property is part of the container dictionary,
|
||||
// or we have a direct reference to a JsonPatchProperty instance
|
||||
|
||||
public bool UseDynamicLogic { get; private set; }
|
||||
|
||||
public bool IsValidPathForAdd { get; private set; }
|
||||
|
||||
public bool IsValidPathForRemove { get; private set; }
|
||||
|
||||
public IDictionary<string, object> Container { get; private set; }
|
||||
|
||||
public string PropertyPathInParent { get; private set; }
|
||||
|
||||
public JsonPatchProperty JsonPatchProperty { get; private set; }
|
||||
|
||||
public ObjectTreeAnalysisResult(
|
||||
object objectToSearch,
|
||||
string propertyPath,
|
||||
IContractResolver contractResolver)
|
||||
{
|
||||
// construct the analysis result.
|
||||
|
||||
// split the propertypath, and if necessary, remove the first
|
||||
// empty item (that's the case when it starts with a "/")
|
||||
var propertyPathTree = propertyPath.Split(
|
||||
new char[] { '/' },
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// we've now got a split up property tree "base/property/otherproperty/..."
|
||||
int lastPosition = 0;
|
||||
object targetObject = objectToSearch;
|
||||
for (int i = 0; i < propertyPathTree.Length; i++)
|
||||
{
|
||||
lastPosition = i;
|
||||
|
||||
// if the current target object is an ExpandoObject (IDictionary<string, object>),
|
||||
// we cannot use the ContractResolver.
|
||||
var dictionary = targetObject as IDictionary<string, object>;
|
||||
if (dictionary != null)
|
||||
{
|
||||
// find the value in the dictionary
|
||||
if (dictionary.ContainsCaseInsensitiveKey(propertyPathTree[i]))
|
||||
{
|
||||
var possibleNewTargetObject = dictionary.GetValueForCaseInsensitiveKey(propertyPathTree[i]);
|
||||
|
||||
// unless we're at the last item, we should set the targetobject
|
||||
// to the new object. If we're at the last item, we need to stop
|
||||
if (i != propertyPathTree.Length - 1)
|
||||
{
|
||||
targetObject = possibleNewTargetObject;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the current part of the path is numeric, this means we're trying
|
||||
// to get the propertyInfo of a specific object in an array. To allow
|
||||
// for this, the previous value (targetObject) must be an IEnumerable, and
|
||||
// the position must exist.
|
||||
|
||||
int numericValue = -1;
|
||||
if (int.TryParse(propertyPathTree[i], out numericValue))
|
||||
{
|
||||
var element = GetElementAtFromObject(targetObject, numericValue);
|
||||
if (element != null)
|
||||
{
|
||||
targetObject = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType());
|
||||
|
||||
// does the property exist?
|
||||
var attemptedProperty = jsonContract
|
||||
.Properties
|
||||
.FirstOrDefault(p => string.Equals(p.PropertyName, propertyPathTree[i], StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (attemptedProperty != null)
|
||||
{
|
||||
// unless we're at the last item, we should continue searching.
|
||||
// If we're at the last item, we need to stop
|
||||
if ((i != propertyPathTree.Length - 1))
|
||||
{
|
||||
targetObject = attemptedProperty.ValueProvider.GetValue(targetObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// property cannot be found, and we're not working with dynamics.
|
||||
// Stop, and return invalid path.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyPathTree.Length - lastPosition != 1)
|
||||
{
|
||||
IsValidPathForAdd = false;
|
||||
IsValidPathForRemove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// two things can happen now. The targetproperty can be an IDictionary - in that
|
||||
// case, it's valid for add if there's 1 item left in the propertyPathTree.
|
||||
//
|
||||
// it can also be a property info. In that case, if there's nothing left in the path
|
||||
// tree we're at the end, if there's one left we can try and set that.
|
||||
if (targetObject is IDictionary<string, object>)
|
||||
{
|
||||
UseDynamicLogic = true;
|
||||
|
||||
Container = (IDictionary<string, object>)targetObject;
|
||||
IsValidPathForAdd = true;
|
||||
PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1];
|
||||
|
||||
// to be able to remove this property, it must exist
|
||||
IsValidPathForRemove = Container.ContainsCaseInsensitiveKey(PropertyPathInParent);
|
||||
}
|
||||
else if (targetObject is IList)
|
||||
{
|
||||
System.Diagnostics.Debugger.Launch();
|
||||
UseDynamicLogic = false;
|
||||
|
||||
int index;
|
||||
if (!Int32.TryParse(propertyPathTree[propertyPathTree.Length - 1], out index))
|
||||
{
|
||||
// We only support indexing into a list
|
||||
IsValidPathForAdd = false;
|
||||
IsValidPathForRemove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
IsValidPathForAdd = true;
|
||||
IsValidPathForRemove = ((IList)targetObject).Count > index;
|
||||
PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
UseDynamicLogic = false;
|
||||
|
||||
var property = propertyPathTree[propertyPathTree.Length - 1];
|
||||
var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType());
|
||||
var attemptedProperty = jsonContract
|
||||
.Properties
|
||||
.FirstOrDefault(p => string.Equals(p.PropertyName, property, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (attemptedProperty == null)
|
||||
{
|
||||
IsValidPathForAdd = false;
|
||||
IsValidPathForRemove = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsValidPathForAdd = true;
|
||||
IsValidPathForRemove = true;
|
||||
JsonPatchProperty = new JsonPatchProperty(attemptedProperty, targetObject);
|
||||
PropertyPathInParent = property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object GetElementAtFromObject(object targetObject, int numericValue)
|
||||
{
|
||||
if (numericValue > -1)
|
||||
{
|
||||
// Check if the targetobject is an IEnumerable,
|
||||
// and if the position is valid.
|
||||
if (targetObject is IEnumerable)
|
||||
{
|
||||
var indexable = ((IEnumerable)targetObject).Cast<object>();
|
||||
|
||||
if (indexable.Count() >= numericValue)
|
||||
{
|
||||
return indexable.ElementAt(numericValue);
|
||||
}
|
||||
else { return null; }
|
||||
}
|
||||
else { return null; }
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Exceptions;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
internal static class PathHelpers
|
||||
{
|
||||
internal static string NormalizePath(string path)
|
||||
{
|
||||
// check for most common path errors on create. This is not
|
||||
// absolutely necessary, but it allows us to already catch mistakes
|
||||
// on creation of the patch document rather than on execute.
|
||||
|
||||
if (path.Contains(".") || path.Contains("//") || path.Contains(" ") || path.Contains("\\"))
|
||||
{
|
||||
throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null);
|
||||
}
|
||||
|
||||
if (!(path.StartsWith("/")))
|
||||
{
|
||||
return "/" + path;
|
||||
}
|
||||
else
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Return value for Remove operation. The combination tells us what to do next (if this operation
|
||||
/// is called from inside another operation, eg: Replace, Copy.
|
||||
///
|
||||
/// Possible combo:
|
||||
/// - ActualType contains type: operation succesfully completed, can continue when called from inside
|
||||
/// another operation
|
||||
/// - ActualType null and HasError true: operation not completed succesfully, should not be allowed to continue
|
||||
/// - ActualType null and HasError false: operation completed succesfully, but we should not be allowed to
|
||||
/// continue when called from inside another method as we could not verify the type of the removed property.
|
||||
/// This happens when the value of an item in an ExpandoObject dictionary is null.
|
||||
/// </summary>
|
||||
internal class RemovedPropertyTypeResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of the removed property (value)
|
||||
/// </summary>
|
||||
public Type ActualType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// HasError: true when an error occurred, the operation didn't complete succesfully
|
||||
/// </summary>
|
||||
public bool HasError { get; set; }
|
||||
|
||||
public RemovedPropertyTypeResult(Type actualType, bool hasError)
|
||||
{
|
||||
ActualType = actualType;
|
||||
HasError = hasError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Operations;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch
|
||||
{
|
||||
public interface IJsonPatchDocument
|
||||
{
|
||||
IContractResolver ContractResolver { get; set; }
|
||||
|
||||
IList<Operation> GetOperations();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Adapters;
|
||||
using Microsoft.AspNet.JsonPatch.Converters;
|
||||
using Microsoft.AspNet.JsonPatch.Helpers;
|
||||
using Microsoft.AspNet.JsonPatch.Operations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch
|
||||
{
|
||||
// Implementation details: the purpose of this type of patch document is to allow creation of such
|
||||
// documents for cases where there's no class/DTO to work on. Typical use case: backend not built in
|
||||
// .NET or architecture doesn't contain a shared DTO layer.
|
||||
[JsonConverter(typeof(JsonPatchDocumentConverter))]
|
||||
public class JsonPatchDocument : IJsonPatchDocument
|
||||
{
|
||||
public List<Operation> Operations { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IContractResolver ContractResolver { get; set; }
|
||||
|
||||
public JsonPatchDocument()
|
||||
{
|
||||
Operations = new List<Operation>();
|
||||
ContractResolver = new DefaultContractResolver();
|
||||
}
|
||||
|
||||
public JsonPatchDocument(List<Operation> operations, IContractResolver contractResolver)
|
||||
{
|
||||
if (operations == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(operations));
|
||||
}
|
||||
|
||||
if (contractResolver == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contractResolver));
|
||||
}
|
||||
|
||||
Operations = operations;
|
||||
ContractResolver = contractResolver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add operation. Will result in, for example,
|
||||
/// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
|
||||
/// </summary>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument Add(string path, object value)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation("add", PathHelpers.NormalizePath(path), null, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove value at target location. Will result in, for example,
|
||||
/// { "op": "remove", "path": "/a/b/c" }
|
||||
/// </summary>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument Remove(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation("remove", PathHelpers.NormalizePath(path), null, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace value. Will result in, for example,
|
||||
/// { "op": "replace", "path": "/a/b/c", "value": 42 }
|
||||
/// </summary>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument Replace(string path, object value)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation("replace", PathHelpers.NormalizePath(path), null, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes value at specified location and add it to the target location. Will result in, for example:
|
||||
/// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
|
||||
/// </summary>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument Move(string from, string path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation("move", PathHelpers.NormalizePath(path), PathHelpers.NormalizePath(from)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the value at specified location to the target location. Willr esult in, for example:
|
||||
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
|
||||
/// </summary>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument Copy(string from, string path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation("copy", PathHelpers.NormalizePath(path), PathHelpers.NormalizePath(from)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply this JsonPatchDocument
|
||||
/// </summary>
|
||||
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
|
||||
public void ApplyTo(object objectToApplyTo)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply this JsonPatchDocument
|
||||
/// </summary>
|
||||
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
|
||||
/// <param name="logErrorAction">Action to log errors</param>
|
||||
public void ApplyTo(object objectToApplyTo, Action<JsonPatchError> logErrorAction)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply this JsonPatchDocument
|
||||
/// </summary>
|
||||
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
|
||||
/// <param name="adapter">IObjectAdapter instance to use when applying</param>
|
||||
public void ApplyTo(object objectToApplyTo, IObjectAdapter adapter)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
if (adapter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(adapter));
|
||||
}
|
||||
|
||||
// apply each operation in order
|
||||
foreach (var op in Operations)
|
||||
{
|
||||
op.Apply(objectToApplyTo, adapter);
|
||||
}
|
||||
}
|
||||
|
||||
IList<Operation> IJsonPatchDocument.GetOperations()
|
||||
{
|
||||
var allOps = new List<Operation>();
|
||||
|
||||
if (Operations != null)
|
||||
{
|
||||
foreach (var op in Operations)
|
||||
{
|
||||
var untypedOp = new Operation();
|
||||
|
||||
untypedOp.op = op.op;
|
||||
untypedOp.value = op.value;
|
||||
untypedOp.path = op.path;
|
||||
untypedOp.from = op.from;
|
||||
|
||||
allOps.Add(untypedOp);
|
||||
}
|
||||
}
|
||||
|
||||
return allOps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,700 @@
|
|||
// 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.Linq.Expressions;
|
||||
using Microsoft.AspNet.JsonPatch.Adapters;
|
||||
using Microsoft.AspNet.JsonPatch.Converters;
|
||||
using Microsoft.AspNet.JsonPatch.Helpers;
|
||||
using Microsoft.AspNet.JsonPatch.Operations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch
|
||||
{
|
||||
// Implementation details: the purpose of this type of patch document is to ensure we can do type-checking
|
||||
// when producing a JsonPatchDocument. However, we cannot send this "typed" over the wire, as that would require
|
||||
// including type data in the JsonPatchDocument serialized as JSON (to allow for correct deserialization) - that's
|
||||
// not according to RFC 6902, and would thus break cross-platform compatibility.
|
||||
[JsonConverter(typeof(TypedJsonPatchDocumentConverter))]
|
||||
public class JsonPatchDocument<TModel> : IJsonPatchDocument where TModel : class
|
||||
{
|
||||
public List<Operation<TModel>> Operations { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IContractResolver ContractResolver { get; set; }
|
||||
|
||||
public JsonPatchDocument()
|
||||
{
|
||||
Operations = new List<Operation<TModel>>();
|
||||
ContractResolver = new DefaultContractResolver();
|
||||
}
|
||||
|
||||
// Create from list of operations
|
||||
public JsonPatchDocument(List<Operation<TModel>> operations, IContractResolver contractResolver)
|
||||
{
|
||||
if (operations == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(operations));
|
||||
}
|
||||
|
||||
if (contractResolver == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contractResolver));
|
||||
}
|
||||
|
||||
Operations = operations;
|
||||
ContractResolver = contractResolver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add operation. Will result in, for example,
|
||||
/// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp">value type</typeparam>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Add<TProp>(Expression<Func<TModel, TProp>> path, TProp value)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"add",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant(),
|
||||
from: null,
|
||||
value: value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add value to list at given position
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp">value type</typeparam>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <param name="position">position</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Add<TProp>(
|
||||
Expression<Func<TModel, IList<TProp>>> path,
|
||||
TProp value,
|
||||
int position)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"add",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position,
|
||||
from: null,
|
||||
value: value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// At value at end of list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp">value type</typeparam>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Add<TProp>(Expression<Func<TModel, IList<TProp>>> path, TProp value)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"add",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-",
|
||||
from: null,
|
||||
value: value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove value at target location. Will result in, for example,
|
||||
/// { "op": "remove", "path": "/a/b/c" }
|
||||
/// </summary>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Remove<TProp>(Expression<Func<TModel, TProp>> path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>("remove", ExpressionHelpers.GetPath(path).ToLowerInvariant(), from: null));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove value from list at given position
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp">value type</typeparam>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="position">position</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Remove<TProp>(Expression<Func<TModel, IList<TProp>>> path, int position)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"remove",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position,
|
||||
from: null));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove value from end of list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp">value type</typeparam>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Remove<TProp>(Expression<Func<TModel, IList<TProp>>> path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"remove",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-",
|
||||
from: null));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace value. Will result in, for example,
|
||||
/// { "op": "replace", "path": "/a/b/c", "value": 42 }
|
||||
/// </summary>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Replace<TProp>(Expression<Func<TModel, TProp>> path, TProp value)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"replace",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant(),
|
||||
from: null,
|
||||
value: value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace value in a list at given position
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp">value type</typeparam>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <param name="position">position</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Replace<TProp>(Expression<Func<TModel, IList<TProp>>> path,
|
||||
TProp value, int position)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"replace",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position,
|
||||
from: null,
|
||||
value: value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace value at end of a list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp">value type</typeparam>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="value">value</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Replace<TProp>(Expression<Func<TModel, IList<TProp>>> path, TProp value)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"replace",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-",
|
||||
from: null,
|
||||
value: value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes value at specified location and add it to the target location. Will result in, for example:
|
||||
/// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
|
||||
/// </summary>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Move<TProp>(
|
||||
Expression<Func<TModel, TProp>> from,
|
||||
Expression<Func<TModel, TProp>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"move",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant(),
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move from a position in a list to a new location
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="positionFrom">position</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Move<TProp>(
|
||||
Expression<Func<TModel, IList<TProp>>> from,
|
||||
int positionFrom,
|
||||
Expression<Func<TModel, TProp>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"move",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant(),
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move from a property to a location in a list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="positionTo">position</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Move<TProp>(
|
||||
Expression<Func<TModel, TProp>> from,
|
||||
Expression<Func<TModel, IList<TProp>>> path,
|
||||
int positionTo)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"move",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo,
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move from a position in a list to another location in a list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="positionFrom">position (source)</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="positionTo">position (target)</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Move<TProp>(
|
||||
Expression<Func<TModel, IList<TProp>>> from,
|
||||
int positionFrom,
|
||||
Expression<Func<TModel, IList<TProp>>> path,
|
||||
int positionTo)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"move",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo,
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move from a position in a list to the end of another list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="positionFrom">position</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Move<TProp>(
|
||||
Expression<Func<TModel, IList<TProp>>> from,
|
||||
int positionFrom,
|
||||
Expression<Func<TModel, IList<TProp>>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"move",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-",
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move to the end of a list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Move<TProp>(
|
||||
Expression<Func<TModel, TProp>> from,
|
||||
Expression<Func<TModel, IList<TProp>>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"move",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-",
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the value at specified location to the target location. Willr esult in, for example:
|
||||
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
|
||||
/// </summary>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Copy<TProp>(
|
||||
Expression<Func<TModel, TProp>> from,
|
||||
Expression<Func<TModel, TProp>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"copy",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant()
|
||||
, ExpressionHelpers.GetPath(from).ToLowerInvariant()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy from a position in a list to a new location
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="positionFrom">position</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Copy<TProp>(
|
||||
Expression<Func<TModel, IList<TProp>>> from,
|
||||
int positionFrom,
|
||||
Expression<Func<TModel, TProp>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"copy",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant(),
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy from a property to a location in a list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="positionTo">position</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Copy<TProp>(
|
||||
Expression<Func<TModel, TProp>> from,
|
||||
Expression<Func<TModel, IList<TProp>>> path,
|
||||
int positionTo)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"copy",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo,
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy from a position in a list to a new location in a list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="positionFrom">position (source)</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <param name="positionTo">position (target)</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Copy<TProp>(
|
||||
Expression<Func<TModel, IList<TProp>>> from,
|
||||
int positionFrom,
|
||||
Expression<Func<TModel, IList<TProp>>> path,
|
||||
int positionTo)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"copy",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo,
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy from a position in a list to the end of another list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="positionFrom">position</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Copy<TProp>(
|
||||
Expression<Func<TModel, IList<TProp>>> from,
|
||||
int positionFrom,
|
||||
Expression<Func<TModel, IList<TProp>>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"copy",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-",
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy to the end of a list
|
||||
/// </summary>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="from">source location</param>
|
||||
/// <param name="path">target location</param>
|
||||
/// <returns></returns>
|
||||
public JsonPatchDocument<TModel> Copy<TProp>(
|
||||
Expression<Func<TModel, TProp>> from,
|
||||
Expression<Func<TModel, IList<TProp>>> path)
|
||||
{
|
||||
if (from == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(from));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
Operations.Add(new Operation<TModel>(
|
||||
"copy",
|
||||
ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-",
|
||||
ExpressionHelpers.GetPath(from).ToLowerInvariant()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply this JsonPatchDocument
|
||||
/// </summary>
|
||||
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
|
||||
public void ApplyTo(TModel objectToApplyTo)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply this JsonPatchDocument
|
||||
/// </summary>
|
||||
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
|
||||
/// <param name="logErrorAction">Action to log errors</param>
|
||||
public void ApplyTo(TModel objectToApplyTo, Action<JsonPatchError> logErrorAction)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply this JsonPatchDocument
|
||||
/// </summary>
|
||||
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
|
||||
/// <param name="adapter">IObjectAdapter instance to use when applying</param>
|
||||
public void ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
if (adapter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(adapter));
|
||||
}
|
||||
|
||||
// apply each operation in order
|
||||
foreach (var op in Operations)
|
||||
{
|
||||
op.Apply(objectToApplyTo, adapter);
|
||||
}
|
||||
}
|
||||
|
||||
IList<Operation> IJsonPatchDocument.GetOperations()
|
||||
{
|
||||
var allOps = new List<Operation>();
|
||||
|
||||
if (Operations != null)
|
||||
{
|
||||
foreach (var op in Operations)
|
||||
{
|
||||
var untypedOp = new Operation();
|
||||
|
||||
untypedOp.op = op.op;
|
||||
untypedOp.value = op.value;
|
||||
untypedOp.path = op.path;
|
||||
untypedOp.from = op.from;
|
||||
|
||||
allOps.Add(untypedOp);
|
||||
}
|
||||
}
|
||||
|
||||
return allOps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Operations;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Captures error message and the related entity and the operation that caused it.
|
||||
/// </summary>
|
||||
public class JsonPatchError
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="JsonPatchError"/>.
|
||||
/// </summary>
|
||||
/// <param name="affectedObject">The object that is affected by the error.</param>
|
||||
/// <param name="operation">The <see cref="Operation"/> that caused the error.</param>
|
||||
/// <param name="errorMessage">The error message.</param>
|
||||
public JsonPatchError(
|
||||
object affectedObject,
|
||||
Operation operation,
|
||||
string errorMessage)
|
||||
{
|
||||
if (errorMessage == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(errorMessage));
|
||||
}
|
||||
|
||||
AffectedObject = affectedObject;
|
||||
Operation = operation;
|
||||
ErrorMessage = errorMessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object that is affected by the error.
|
||||
/// </summary>
|
||||
public object AffectedObject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Operation"/> that caused the error.
|
||||
/// </summary>
|
||||
public Operation Operation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error message.
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>4d55f4d8-633b-462f-a5b1-feb84bd2d534</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Adapters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Operations
|
||||
{
|
||||
public class Operation : OperationBase
|
||||
{
|
||||
[JsonProperty("value")]
|
||||
public object value { get; set; }
|
||||
|
||||
public Operation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Operation(string op, string path, string from, object value)
|
||||
: base(op, path, from)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Operation(string op, string path, string from)
|
||||
: base(op, path, from)
|
||||
{
|
||||
}
|
||||
|
||||
public void Apply(object objectToApplyTo, IObjectAdapter adapter)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
if (adapter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(adapter));
|
||||
}
|
||||
|
||||
switch (OperationType)
|
||||
{
|
||||
case OperationType.Add:
|
||||
adapter.Add(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Remove:
|
||||
adapter.Remove(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Replace:
|
||||
adapter.Replace(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Move:
|
||||
adapter.Move(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Copy:
|
||||
adapter.Copy(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Test:
|
||||
throw new NotSupportedException(Resources.TestOperationNotSupported);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShouldSerializevalue()
|
||||
{
|
||||
return (OperationType == OperationType.Add
|
||||
|| OperationType == OperationType.Replace
|
||||
|| OperationType == OperationType.Test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// 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 Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Operations
|
||||
{
|
||||
public class OperationBase
|
||||
{
|
||||
[JsonIgnore]
|
||||
public OperationType OperationType
|
||||
{
|
||||
get
|
||||
{
|
||||
return (OperationType)Enum.Parse(typeof(OperationType), op, true);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty("path")]
|
||||
public string path { get; set; }
|
||||
|
||||
[JsonProperty("op")]
|
||||
public string op { get; set; }
|
||||
|
||||
[JsonProperty("from")]
|
||||
public string from { get; set; }
|
||||
|
||||
public OperationBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public OperationBase(string op, string path, string from)
|
||||
{
|
||||
if (op == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(op));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
this.op = op;
|
||||
this.path = path;
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public bool ShouldSerializefrom()
|
||||
{
|
||||
return (OperationType == OperationType.Move
|
||||
|| OperationType == OperationType.Copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Adapters;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Operations
|
||||
{
|
||||
public class Operation<TModel> : Operation where TModel : class
|
||||
{
|
||||
public Operation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Operation(string op, string path, string from, object value)
|
||||
: base(op, path, from)
|
||||
{
|
||||
if (op == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(op));
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Operation(string op, string path, string from)
|
||||
: base(op, path, from)
|
||||
{
|
||||
if (op == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(op));
|
||||
}
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Apply(TModel objectToApplyTo, IObjectAdapter adapter)
|
||||
{
|
||||
if (objectToApplyTo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(objectToApplyTo));
|
||||
}
|
||||
|
||||
if (adapter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(adapter));
|
||||
}
|
||||
|
||||
switch (OperationType)
|
||||
{
|
||||
case OperationType.Add:
|
||||
adapter.Add(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Remove:
|
||||
adapter.Remove(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Replace:
|
||||
adapter.Replace(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Move:
|
||||
adapter.Move(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Copy:
|
||||
adapter.Copy(this, objectToApplyTo);
|
||||
break;
|
||||
case OperationType.Test:
|
||||
throw new NotSupportedException(Resources.TestOperationNotSupported);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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.AspNet.JsonPatch.Operations
|
||||
{
|
||||
public enum OperationType
|
||||
{
|
||||
Add,
|
||||
Remove,
|
||||
Replace,
|
||||
Move,
|
||||
Copy,
|
||||
Test
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// 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.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.AspNet.JsonPatch
|
||||
{
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
internal static class Resources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNet.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 read.
|
||||
/// </summary>
|
||||
internal static string CannotReadProperty
|
||||
{
|
||||
get { return 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The property at path '{0}' could not be updated.
|
||||
/// </summary>
|
||||
internal static string CannotUpdateProperty
|
||||
{
|
||||
get { return 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The key '{0}' was not found.
|
||||
/// </summary>
|
||||
internal static string DictionaryKeyNotFound
|
||||
{
|
||||
get { return GetString("DictionaryKeyNotFound"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The key '{0}' was not found.
|
||||
/// </summary>
|
||||
internal static string FormatDictionaryKeyNotFound(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DictionaryKeyNotFound"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For operation '{0}' on array property at path '{1}', the index is larger than the array size.
|
||||
/// </summary>
|
||||
internal static string InvalidIndexForArrayProperty
|
||||
{
|
||||
get { return GetString("InvalidIndexForArrayProperty"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For operation '{0}' on array property at path '{1}', the index is larger than the array size.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidIndexForArrayProperty(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexForArrayProperty"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type '{0}' was malformed and could not be parsed.
|
||||
/// </summary>
|
||||
internal static string InvalidJsonPatchDocument
|
||||
{
|
||||
get { return 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For operation '{0}', the provided path is invalid for array property at path '{1}'.
|
||||
/// </summary>
|
||||
internal static string InvalidPathForArrayProperty
|
||||
{
|
||||
get { return GetString("InvalidPathForArrayProperty"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For operation '{0}', the provided path is invalid for array property at path '{1}'.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidPathForArrayProperty(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidPathForArrayProperty"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The provided string '{0}' is an invalid path.
|
||||
/// </summary>
|
||||
internal static string InvalidValueForPath
|
||||
{
|
||||
get { return 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value '{0}' is invalid for property at path '{1}'.
|
||||
/// </summary>
|
||||
internal static string InvalidValueForProperty
|
||||
{
|
||||
get { return GetString("InvalidValueForProperty"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value '{0}' is invalid for property at path '{1}'.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidValueForProperty(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For operation '{0}' on array property at path '{1}', the index is negative.
|
||||
/// </summary>
|
||||
internal static string NegativeIndexForArrayProperty
|
||||
{
|
||||
get { return GetString("NegativeIndexForArrayProperty"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For operation '{0}' on array property at path '{1}', the index is negative.
|
||||
/// </summary>
|
||||
internal static string FormatNegativeIndexForArrayProperty(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("NegativeIndexForArrayProperty"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// '{0}' must be of type '{1}'.
|
||||
/// </summary>
|
||||
internal static string ParameterMustMatchType
|
||||
{
|
||||
get { return 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The property at path '{0}' could not be added.
|
||||
/// </summary>
|
||||
internal static string PropertyCannotBeAdded
|
||||
{
|
||||
get { return GetString("PropertyCannotBeAdded"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The property at path '{0}' could not be added.
|
||||
/// </summary>
|
||||
internal static string FormatPropertyCannotBeAdded(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyCannotBeAdded"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The property at path '{0}' could not be removed.
|
||||
/// </summary>
|
||||
internal static string PropertyCannotBeRemoved
|
||||
{
|
||||
get { return GetString("PropertyCannotBeRemoved"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The property at path '{0}' could not be removed.
|
||||
/// </summary>
|
||||
internal static string FormatPropertyCannotBeRemoved(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyCannotBeRemoved"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property does not exist at path '{0}'.
|
||||
/// </summary>
|
||||
internal static string PropertyDoesNotExist
|
||||
{
|
||||
get { return GetString("PropertyDoesNotExist"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property does not exist at path '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatPropertyDoesNotExist(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyDoesNotExist"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The test operation is not supported.
|
||||
/// </summary>
|
||||
internal static string TestOperationNotSupported
|
||||
{
|
||||
get { return GetString("TestOperationNotSupported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The test operation is not supported.
|
||||
/// </summary>
|
||||
internal static string FormatTestOperationNotSupported()
|
||||
{
|
||||
return GetString("TestOperationNotSupported");
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
||||
System.Diagnostics.Debug.Assert(value != null);
|
||||
|
||||
if (formatterNames != null)
|
||||
{
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="CannotDeterminePropertyType" xml:space="preserve">
|
||||
<value>The type of the property at path '{0}' could not be determined.</value>
|
||||
</data>
|
||||
<data name="CannotReadProperty" xml:space="preserve">
|
||||
<value>The property at '{0}' could not be read.</value>
|
||||
</data>
|
||||
<data name="CannotUpdateProperty" xml:space="preserve">
|
||||
<value>The property at path '{0}' could not be updated.</value>
|
||||
</data>
|
||||
<data name="DictionaryKeyNotFound" xml:space="preserve">
|
||||
<value>The key '{0}' was not found.</value>
|
||||
</data>
|
||||
<data name="InvalidIndexForArrayProperty" xml:space="preserve">
|
||||
<value>For operation '{0}' on array property at path '{1}', the index is larger than the array size.</value>
|
||||
</data>
|
||||
<data name="InvalidJsonPatchDocument" xml:space="preserve">
|
||||
<value>The type '{0}' was malformed and could not be parsed.</value>
|
||||
</data>
|
||||
<data name="InvalidPathForArrayProperty" xml:space="preserve">
|
||||
<value>For operation '{0}', the provided path is invalid for array property at path '{1}'.</value>
|
||||
</data>
|
||||
<data name="InvalidValueForPath" xml:space="preserve">
|
||||
<value>The provided string '{0}' is an invalid path.</value>
|
||||
</data>
|
||||
<data name="InvalidValueForProperty" xml:space="preserve">
|
||||
<value>The value '{0}' is invalid for property at path '{1}'.</value>
|
||||
</data>
|
||||
<data name="NegativeIndexForArrayProperty" xml:space="preserve">
|
||||
<value>For operation '{0}' on array property at path '{1}', the index is negative.</value>
|
||||
</data>
|
||||
<data name="ParameterMustMatchType" xml:space="preserve">
|
||||
<value>'{0}' must be of type '{1}'.</value>
|
||||
</data>
|
||||
<data name="PropertyCannotBeAdded" xml:space="preserve">
|
||||
<value>The property at path '{0}' could not be added.</value>
|
||||
</data>
|
||||
<data name="PropertyCannotBeRemoved" xml:space="preserve">
|
||||
<value>The property at path '{0}' could not be removed.</value>
|
||||
</data>
|
||||
<data name="PropertyDoesNotExist" xml:space="preserve">
|
||||
<value>Property does not exist at path '{0}'.</value>
|
||||
</data>
|
||||
<data name="TestOperationNotSupported" xml:space="preserve">
|
||||
<value>The test operation is not supported.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/mvc"
|
||||
},
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "6.0.6"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"Microsoft.CSharp": "4.0.1-beta-*",
|
||||
"System.Collections.Concurrent": "4.0.11-beta-*",
|
||||
"System.ComponentModel.TypeConverter": "4.0.1-beta-*",
|
||||
"System.Globalization": "4.0.11-beta-*",
|
||||
"System.Reflection.Extensions": "4.0.1-beta-*",
|
||||
"System.Resources.ResourceManager": "4.0.1-beta-*",
|
||||
"System.Runtime.Extensions": "4.0.11-beta-*",
|
||||
"System.Text.Encoding.Extensions": "4.0.11-beta-*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,569 @@
|
|||
// 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.Dynamic;
|
||||
using Microsoft.AspNet.JsonPatch.Exceptions;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class AddOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddNewPropertyShouldFailIfRootIsNotAnExpandoObject()
|
||||
{
|
||||
dynamic doc = new
|
||||
{
|
||||
Test = 1
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("NewInt", 1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/NewInt' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddNewProperty()
|
||||
{
|
||||
dynamic obj = new ExpandoObject();
|
||||
obj.Test = 1;
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("NewInt", 1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(obj);
|
||||
|
||||
Assert.Equal(1, obj.NewInt);
|
||||
Assert.Equal(1, obj.Test);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddNewPropertyToNestedAnonymousObjectShouldFail()
|
||||
{
|
||||
dynamic doc = new
|
||||
{
|
||||
Test = 1,
|
||||
nested = new { }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("Nested/NewInt", 1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/Nested/NewInt' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddNewPropertyToTypedObjectShouldFail()
|
||||
{
|
||||
dynamic doc = new
|
||||
{
|
||||
Test = 1,
|
||||
nested = new NestedDTO()
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("Nested/NewInt", 1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/Nested/NewInt' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToExistingPropertyOnNestedObject()
|
||||
{
|
||||
dynamic doc = new
|
||||
{
|
||||
Test = 1,
|
||||
nested = new NestedDTO()
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("Nested/StringProperty", "A");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.nested.StringProperty);
|
||||
Assert.Equal(1, doc.Test);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddNewPropertyToExpandoOject()
|
||||
{
|
||||
dynamic doc = new
|
||||
{
|
||||
Test = 1,
|
||||
nested = new ExpandoObject()
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("Nested/NewInt", 1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.nested.NewInt);
|
||||
Assert.Equal(1, doc.Test);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddNewPropertyToExpandoOjectInTypedObject()
|
||||
{
|
||||
var doc = new NestedDTO()
|
||||
{
|
||||
DynamicProperty = new ExpandoObject()
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("DynamicProperty/NewInt", 1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.DynamicProperty.NewInt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddNewPropertyToTypedObjectInExpandoObject()
|
||||
{
|
||||
dynamic dynamicProperty = new ExpandoObject();
|
||||
dynamicProperty.StringProperty = "A";
|
||||
|
||||
var doc = new NestedDTO()
|
||||
{
|
||||
DynamicProperty = dynamicProperty
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("DynamicProperty/StringProperty", "B");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("B", doc.DynamicProperty.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddNewPropertyToAnonymousObjectShouldFail()
|
||||
{
|
||||
dynamic doc = new
|
||||
{
|
||||
Test = 1
|
||||
};
|
||||
|
||||
dynamic valueToAdd = new { IntValue = 1, StringValue = "test", GuidValue = Guid.NewGuid() };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("ComplexProperty", valueToAdd);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/ComplexProperty' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddResultsReplaceShouldFailOnAnonymousDueToNoSetter()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
StringProperty = "A"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("StringProperty", "B");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/StringProperty' could not be updated.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddResultsShouldReplace()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.StringProperty = "A";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("StringProperty", "B");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("B", doc.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddResultsShouldReplaceInNested()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.InBetweenFirst = new ExpandoObject();
|
||||
doc.InBetweenFirst.InBetweenSecond = new ExpandoObject();
|
||||
doc.InBetweenFirst.InBetweenSecond.StringProperty = "A";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("/InBetweenFirst/InBetweenSecond/StringProperty", "B");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("B", doc.InBetweenFirst.InBetweenSecond.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddResultsShouldReplaceInNestedInDynamic()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Nested = new NestedDTO();
|
||||
doc.Nested.DynamicProperty = new ExpandoObject();
|
||||
doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject();
|
||||
doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject();
|
||||
doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("B", doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldNotBeAbleToAddToNonExistingPropertyThatIsNotTheRoot()
|
||||
{
|
||||
//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.
|
||||
|
||||
var doc = new NestedDTO()
|
||||
{
|
||||
DynamicProperty = new ExpandoObject()
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/DynamicProperty/OtherProperty/IntProperty' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldNotBeAbleToAddToNonExistingPropertyInNestedPropertyThatIsNotTheRoot()
|
||||
{
|
||||
//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.
|
||||
|
||||
var doc = new
|
||||
{
|
||||
Foo = "bar"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("baz/bat", "qux");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/baz/bat' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldReplacePropertyWithDifferentCase()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.StringProperty = "A";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("stringproperty", "B");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("B", doc.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToList()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("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.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListNegativePosition()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("IntegerList/-1", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'add' on array property at path '/IntegerList/-1', the index is negative.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldAddToListWithDifferentCase()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("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.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListInvalidPositionTooLarge()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("IntegerList/4", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'add' on array property at path '/IntegerList/4', the index is larger than the array size.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListAtEndWithSerialization()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("IntegerList/3", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 4 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListAtBeginning()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("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.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListInvalidPositionTooSmall()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("IntegerList/-1", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'add' on array property at path '/IntegerList/-1', the index is negative.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListAppend()
|
||||
{
|
||||
var doc = new
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("IntegerList/-", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 4 }, doc.IntegerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// 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.AspNet.JsonPatch.Exceptions;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class AddTypedOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddToListNegativePosition()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("IntegerList/-1", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'add' on array property at path '/IntegerList/-1', the index is negative.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListInList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
ListOfSimpleDTO = new List<SimpleDTO>()
|
||||
{
|
||||
new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("ListOfSimpleDTO/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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListInListInvalidPositionTooSmall()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
ListOfSimpleDTO = new List<SimpleDTO>()
|
||||
{
|
||||
new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("ListOfSimpleDTO/-1/IntegerList/0", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/ListOfSimpleDTO/-1/IntegerList/0' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddToListInListInvalidPositionTooLarge()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
ListOfSimpleDTO = new List<SimpleDTO>()
|
||||
{
|
||||
new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
}
|
||||
};
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/ListOfSimpleDTO/20/IntegerList/0' could not be added.",
|
||||
exception.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class CopyOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void Copy()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
|
||||
doc.StringProperty = "A";
|
||||
doc.AnotherStringProperty = "B";
|
||||
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("StringProperty", "AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.AnotherStringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyInList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerList/0", "IntegerList/1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyFromListToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerList/0", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyFromListToNonList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerList/0", "IntegerValue");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.IntegerValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyFromNonListToList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerValue = 5;
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerValue", "IntegerList/0");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerValue = 5;
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerValue", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopy()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A",
|
||||
AnotherStringProperty = "B"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyInList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyFromListToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyFromListToNonList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.SimpleDTO.IntegerValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyFromNonListToList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0");
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class CopyTypedOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void Copy()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A",
|
||||
AnotherStringProperty = "B"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("StringProperty", "AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.AnotherStringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyInList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerList/0", "IntegerList/1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyFromListToEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerList/0", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyFromListToNonList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerList/0", "IntegerValue");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.IntegerValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyFromNonListToList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerValue", "IntegerList/0");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyToEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("IntegerValue", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopy()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A",
|
||||
AnotherStringProperty = "B"
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyInList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyFromListToEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyFromListToNonList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.SimpleDTO.IntegerValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyFromNonListToList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0");
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCopyToEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,338 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class MoveOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void Move()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.StringProperty = "A";
|
||||
doc.AnotherStringProperty = "B";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("StringProperty", "AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.AnotherStringProperty);
|
||||
|
||||
var cont = doc as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
cont.TryGetValue("StringProperty", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveToNonExisting()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.StringProperty = "A";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("StringProperty", "AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.AnotherStringProperty);
|
||||
|
||||
var cont = doc as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
cont.TryGetValue("StringProperty", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveDynamicToTyped()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.StringProperty = "A";
|
||||
doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("StringProperty", "SimpleDTO/AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty);
|
||||
|
||||
var cont = doc as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
cont.TryGetValue("StringProperty", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveTypedToDynamic()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.StringProperty = "A";
|
||||
doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("SimpleDTO/AnotherStringProperty", "StringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("B", doc.StringProperty);
|
||||
Assert.Equal(null, doc.SimpleDTO.AnotherStringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedMove()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Nested = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A",
|
||||
AnotherStringProperty = "B"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("Nested/StringProperty", "Nested/AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.Nested.AnotherStringProperty);
|
||||
Assert.Equal(null, doc.Nested.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveInList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerList/0", "IntegerList/1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 1, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedMoveInList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Nested = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 1, 3 }, doc.Nested.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveFromListToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerList/0", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 3, 1 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedMoveFromListToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Nested = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 3, 1 }, doc.Nested.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveFomListToNonList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerList/0", "IntegerValue");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 3 }, doc.IntegerList);
|
||||
Assert.Equal(1, doc.IntegerValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedMoveFomListToNonList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Nested = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 3 }, doc.Nested.IntegerList);
|
||||
Assert.Equal(1, doc.Nested.IntegerValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveFromNonListToList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerValue = 5;
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerValue", "IntegerList/0");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
var cont = doc as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
cont.TryGetValue("IntegerValue", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
|
||||
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedMoveFromNonListToList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Nested = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/0");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(0, doc.Nested.IntegerValue);
|
||||
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.Nested.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerValue = 5;
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerValue", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
var cont = doc as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
cont.TryGetValue("IntegerValue", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedMoveToEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Nested = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(0, doc.Nested.IntegerValue);
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.Nested.IntegerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class MoveTypedOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void Move()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A",
|
||||
AnotherStringProperty = "B"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("StringProperty", "AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.AnotherStringProperty);
|
||||
Assert.Equal(null, doc.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveInList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerList/0", "IntegerList/1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 1, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveFromListToEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerList/0", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 3, 1 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveFomListToNonList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerList/0", "IntegerValue");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 2, 3 }, doc.IntegerList);
|
||||
Assert.Equal(1, doc.IntegerValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveFromNonListToList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerValue", "IntegerList/0");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(0, doc.IntegerValue);
|
||||
Assert.Equal(new List<int>() { 5, 1, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveToEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Move("IntegerValue", "IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(0, doc.IntegerValue);
|
||||
Assert.Equal(new List<int>() { 1, 2, 3, 5 }, doc.IntegerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class NestedDTO
|
||||
{
|
||||
public string StringProperty { get; set; }
|
||||
public dynamic DynamicProperty { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
// 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 Microsoft.AspNet.JsonPatch.Exceptions;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class PatchDocumentTests
|
||||
{
|
||||
[Fact]
|
||||
public void InvalidPathAtBeginningShouldThrowException()
|
||||
{
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
patchDoc.Add("//NewInt", 1);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The provided string '//NewInt' is an invalid path.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidPathAtEndShouldThrowException()
|
||||
{
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
patchDoc.Add("NewInt//", 1);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The provided string 'NewInt//' is an invalid path.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidPathWithDotShouldThrowException()
|
||||
{
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
patchDoc.Add("NewInt.Test", 1);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The provided string 'NewInt.Test' is an invalid path.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NonGenericPatchDocToGenericMustSerialize()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A",
|
||||
AnotherStringProperty = "B"
|
||||
};
|
||||
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Copy("StringProperty", "AnotherStringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleDTO>>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.AnotherStringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericPatchDocToNonGenericMustSerialize()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A",
|
||||
AnotherStringProperty = "B"
|
||||
};
|
||||
|
||||
JsonPatchDocument<SimpleDTO> patchDocTyped = new JsonPatchDocument<SimpleDTO>();
|
||||
patchDocTyped.Copy<string>(o => o.StringProperty, o => o.AnotherStringProperty);
|
||||
|
||||
JsonPatchDocument patchDocUntyped = new JsonPatchDocument();
|
||||
patchDocUntyped.Copy("StringProperty", "AnotherStringProperty");
|
||||
|
||||
var serializedTyped = JsonConvert.SerializeObject(patchDocTyped);
|
||||
var serializedUntyped = JsonConvert.SerializeObject(patchDocUntyped);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serializedTyped);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal("A", doc.AnotherStringProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using Microsoft.AspNet.JsonPatch.Exceptions;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class RemoveOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void RemovePropertyShouldFailIfRootIsAnonymous()
|
||||
{
|
||||
dynamic doc = new
|
||||
{
|
||||
Test = 1
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("Test");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/Test' could not be updated.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemovePropertyShouldFailIfItDoesntExist()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.Test = 1;
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("NonExisting");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"The property at path '/NonExisting' could not be removed.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemovePropertyFromExpandoObject()
|
||||
{
|
||||
dynamic obj = new ExpandoObject();
|
||||
obj.Test = 1;
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("Test");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(obj);
|
||||
|
||||
var cont = obj as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
|
||||
cont.TryGetValue("Test", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemovePropertyFromExpandoObjectMixedCase()
|
||||
{
|
||||
dynamic obj = new ExpandoObject();
|
||||
obj.Test = 1;
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("test");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(obj);
|
||||
|
||||
var cont = obj as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
|
||||
cont.TryGetValue("Test", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveNestedPropertyFromExpandoObject()
|
||||
{
|
||||
dynamic obj = new ExpandoObject();
|
||||
obj.Test = new ExpandoObject();
|
||||
obj.Test.AnotherTest = "A";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("Test");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(obj);
|
||||
|
||||
var cont = obj as IDictionary<string, object>;
|
||||
object valueFromDictionary;
|
||||
|
||||
cont.TryGetValue("Test", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveNestedPropertyFromExpandoObjectMixedCase()
|
||||
{
|
||||
dynamic obj = new ExpandoObject();
|
||||
obj.Test = new ExpandoObject();
|
||||
obj.Test.AnotherTest = "A";
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("test");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(obj);
|
||||
var cont = obj as IDictionary<string, object>;
|
||||
|
||||
object valueFromDictionary;
|
||||
cont.TryGetValue("Test", out valueFromDictionary);
|
||||
Assert.Null(valueFromDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemove()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/StringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
Assert.Equal(null, doc.SimpleDTO.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveMixedCase()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("Simpledto/stringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(null, doc.SimpleDTO.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromListMixedCase()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromListInvalidPositionTooLarge()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/IntegerList/3");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromListInvalidPositionTooSmall()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/IntegerList/-1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
// 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.AspNet.JsonPatch.Exceptions;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class RemoveTypedOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void Remove()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A"
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("StringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(null, doc.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveFromList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("IntegerList/2");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveFromListInvalidPositionTooLarge()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("IntegerList/3");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'remove' on array property at path '/IntegerList/3', the index is larger than the array size.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveFromListInvalidPositionTooSmall()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("IntegerList/-1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'remove' on array property at path '/IntegerList/-1', the index is negative.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveFromEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("IntegerList/-");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemove()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
StringProperty = "A"
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/StringProperty");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(null, doc.SimpleDTO.StringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromListInvalidPositionTooLarge()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/IntegerList/3");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromListInvalidPositionTooSmall()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/IntegerList/-1");
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||
{
|
||||
deserialized.ApplyTo(doc);
|
||||
});
|
||||
Assert.Equal(
|
||||
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedRemoveFromEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Remove("SimpleDTO/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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Dynamic;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class ReplaceOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReplaceGuidTest()
|
||||
{
|
||||
dynamic doc = new SimpleDTO()
|
||||
{
|
||||
GuidValue = Guid.NewGuid()
|
||||
};
|
||||
|
||||
var newGuid = Guid.NewGuid();
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("GuidValue", newGuid);
|
||||
|
||||
// serialize & deserialize
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserizalized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(newGuid, doc.GuidValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceGuidTestExpandoObject()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.GuidValue = Guid.NewGuid();
|
||||
|
||||
var newGuid = Guid.NewGuid();
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("GuidValue", newGuid);
|
||||
|
||||
// serialize & deserialize
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserizalized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(newGuid, doc.GuidValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceGuidTestExpandoObjectInAnonymous()
|
||||
{
|
||||
dynamic nestedObject = new ExpandoObject();
|
||||
nestedObject.GuidValue = Guid.NewGuid();
|
||||
|
||||
dynamic doc = new
|
||||
{
|
||||
NestedObject = nestedObject
|
||||
};
|
||||
|
||||
var newGuid = Guid.NewGuid();
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("nestedobject/GuidValue", newGuid);
|
||||
|
||||
// serialize & deserialize
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserizalized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(newGuid, doc.NestedObject.GuidValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceNestedObjectTest()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
var newDTO = new SimpleDTO()
|
||||
{
|
||||
DoubleValue = 1
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("SimpleDTO", newDTO);
|
||||
|
||||
// serialize & deserialize
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.SimpleDTO.DoubleValue);
|
||||
Assert.Equal(0, doc.SimpleDTO.IntegerValue);
|
||||
Assert.Equal(null, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceInList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList/0", 5);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 5, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceFullList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceInListInList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTOList = new List<SimpleDTO>() {
|
||||
new SimpleDTO() {
|
||||
IntegerList = new List<int>(){1,2,3}
|
||||
}};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceInListInListAtEnd()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.SimpleDTOList = new List<SimpleDTO>() {
|
||||
new SimpleDTO() {
|
||||
IntegerList = new List<int>(){1,2,3}
|
||||
}};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("SimpleDTOList/0/IntegerList/-", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[2]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceFullListFromEnumerable()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceFullListWithCollection()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList", new Collection<int>() { 4, 5, 6 });
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceAtEndOfList()
|
||||
{
|
||||
dynamic doc = new ExpandoObject();
|
||||
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList/-", 5);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 5 }, doc.IntegerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class ReplaceTypedOperationTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReplaceGuidTest()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
GuidValue = Guid.NewGuid()
|
||||
};
|
||||
|
||||
var newGuid = Guid.NewGuid();
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("GuidValue", newGuid);
|
||||
|
||||
// serialize & deserialize
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserizalized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserizalized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(newGuid, doc.GuidValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SerializeAndReplaceNestedObjectTest()
|
||||
{
|
||||
var doc = new SimpleDTOWithNestedDTO()
|
||||
{
|
||||
SimpleDTO = new SimpleDTO()
|
||||
{
|
||||
IntegerValue = 5,
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
var newDTO = new SimpleDTO()
|
||||
{
|
||||
DoubleValue = 1
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("SimpleDTO", newDTO);
|
||||
|
||||
// serialize & deserialize
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(1, doc.SimpleDTO.DoubleValue);
|
||||
Assert.Equal(0, doc.SimpleDTO.IntegerValue);
|
||||
Assert.Equal(null, doc.SimpleDTO.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceInList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList/0", 5);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 5, 2, 3 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceFullList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceInListInList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
SimpleDTOList = new List<SimpleDTO>() {
|
||||
new SimpleDTO() {
|
||||
IntegerList = new List<int>(){1,2,3}
|
||||
}}
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(4, doc.SimpleDTOList.First().IntegerList.First());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceFullListFromEnumerable()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList", new List<int>() { 4, 5, 6 });
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceFullListWithCollection()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList", new Collection<int>() { 4, 5, 6 });
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 4, 5, 6 }, doc.IntegerList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceAtEndOfList()
|
||||
{
|
||||
var doc = new SimpleDTO()
|
||||
{
|
||||
IntegerList = new List<int>() { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// create patch
|
||||
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||
patchDoc.Replace("IntegerList/-", 5);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||
deserialized.ApplyTo(doc);
|
||||
|
||||
Assert.Equal(new List<int>() { 1, 2, 5 }, doc.IntegerList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||
{
|
||||
public class SimpleDTO
|
||||
{
|
||||
public List<SimpleDTO> SimpleDTOList { get; set; }
|
||||
public List<int> IntegerList { get; set; }
|
||||
public int IntegerValue { get; set; }
|
||||
public string StringProperty { get; set; }
|
||||
public string AnotherStringProperty { get; set; }
|
||||
public decimal DecimalValue { get; set; }
|
||||
public double DoubleValue { get; set; }
|
||||
public float FloatValue { get; set; }
|
||||
public Guid GuidValue { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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.AspNet.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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>81c20848-e063-4e12-ac40-0b55a532c16c</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -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.AspNet.JsonPatch.Test
|
||||
{
|
||||
public class NestedDTO
|
||||
{
|
||||
public string StringProperty { get; set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.JsonPatch.Test
|
||||
{
|
||||
public class SimpleDTO
|
||||
{
|
||||
public List<int> IntegerList { get; set; }
|
||||
public IList<int> IntegerIList { get; set; }
|
||||
public int IntegerValue { get; set; }
|
||||
public string StringProperty { get; set; }
|
||||
public string AnotherStringProperty { get; set; }
|
||||
public decimal DecimalValue { get; set; }
|
||||
public double DoubleValue { get; set; }
|
||||
public float FloatValue { get; set; }
|
||||
public Guid GuidValue { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.AspNet.JsonPatch.Test
|
||||
{
|
||||
public class SimpleDTOWithNestedDTO
|
||||
{
|
||||
public int IntegerValue { get; set; }
|
||||
|
||||
public NestedDTO NestedDTO { get; set; }
|
||||
|
||||
public SimpleDTO SimpleDTO { 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.SimpleDTOList = new List<SimpleDTO>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.AspNet.JsonPatch.Test
|
||||
{
|
||||
public class TestErrorLogger<T> where T: class
|
||||
{
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public void LogErrorMessage(JsonPatchError patchError)
|
||||
{
|
||||
ErrorMessage = patchError.ErrorMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"compilationOptions": {
|
||||
"warningsAsErrors": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.JsonPatch": "1.0.0-*",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"Moq": "4.2.1312.1622",
|
||||
"Newtonsoft.Json": "6.0.6",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
},
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue