Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions AspNetCore.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@
<Project Path="src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/Microsoft.AspNetCore.Tests.csproj" />
</Folder>
<Folder Name="/src/Features/" Id="e81caa0a-8d6a-e3b6-28b3-ab416e1657a7" />
<Folder Name="/src/Features/JsonPatch.SystemTextJson/" Id="02ea681e-c7d8-13c7-8484-4ac65e1b71e8">
<Project Path="src/Features/JsonPatch.SystemTextJson/src/Microsoft.AspNetCore.JsonPatch.SystemTextJson.csproj" />
<Project Path="src/Features/JsonPatch.SystemTextJson/test/Microsoft.AspNetCore.JsonPatch.SystemTextJson.Tests.csproj" />
</Folder>
<Folder Name="/src/Features/JsonPatch/" Id="077a40ee-d664-9e06-acde-21ca54b47638">
<Project Path="src/Features/JsonPatch/src/Microsoft.AspNetCore.JsonPatch.csproj" />
<Project Path="src/Features/JsonPatch/test/Microsoft.AspNetCore.JsonPatch.Tests.csproj" />
Expand Down
12 changes: 12 additions & 0 deletions src/Features/JsonPatch.SystemTextJson/.vsconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "1.0",
"components": [
"Microsoft.Net.Component.4.6.2.TargetingPack",
"Microsoft.Net.Component.4.7.2.SDK",
"Microsoft.Net.Component.4.7.2.TargetingPack",
"Microsoft.VisualStudio.Workload.ManagedDesktop",
"Microsoft.VisualStudio.Workload.NetCoreTools",
"Microsoft.VisualStudio.Workload.NetWeb",
"Microsoft.VisualStudio.Workload.VisualStudioExtension"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"solution": {
"path": "..\\..\\..\\AspNetCore.slnx",
"projects" : [
"src\\Features\\JsonPatch.SystemTextJson\\src\\Microsoft.AspNetCore.JsonPatch.SystemTextJson.csproj",
"src\\Features\\JsonPatch.SystemTextJson\\test\\Microsoft.AspNetCore.JsonPatch.SystemTextJson.Tests.csproj"
]
}
}
4 changes: 4 additions & 0 deletions src/Features/JsonPatch.SystemTextJson/build.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

@ECHO OFF
SET RepoRoot=%~dp0..\..\..
%RepoRoot%\eng\build.cmd -projects %~dp0**\*.*proj %*
7 changes: 7 additions & 0 deletions src/Features/JsonPatch.SystemTextJson/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash

set -euo pipefail

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
repo_root="$DIR/../.."
"$repo_root/eng/build.sh" --projects "$DIR/**/*.*proj" "$@"
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.JsonPatch.SystemTextJson.Internal;
using Microsoft.AspNetCore.Shared;

namespace Microsoft.AspNetCore.JsonPatch.SystemTextJson.Adapters;

/// <summary>
/// The default AdapterFactory to be used for resolving <see cref="IAdapter"/>.
/// </summary>
internal class AdapterFactory : IAdapterFactory
{
internal static AdapterFactory Default { get; } = new();

/// <inheritdoc />
public virtual IAdapter Create(object target)
{
ArgumentNullThrowHelper.ThrowIfNull(target);

var typeToConvert = target.GetType();
if (typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
return (IAdapter)Activator.CreateInstance(typeof(DictionaryAdapter<,>).MakeGenericType(typeToConvert.GenericTypeArguments[0], typeToConvert.GenericTypeArguments[1]));
}

return target switch
{
JsonObject => new JsonObjectAdapter(),
JsonArray => new ListAdapter(),
IList => new ListAdapter(),
_ => new PocoAdapter()
};
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.JsonPatch.SystemTextJson.Internal;

namespace Microsoft.AspNetCore.JsonPatch.SystemTextJson.Adapters;

/// <summary>
/// Defines the operations used for loading an <see cref="IAdapter"/> based on the current object and ContractResolver.
/// </summary>
public interface IAdapterFactory
{
/// <summary>
/// Creates an <see cref="IAdapter"/> for the current object
/// </summary>
/// <param name="target">The target object</param>
/// <returns>The needed <see cref="IAdapter"/></returns>
IAdapter Create(object target);
}
111 changes: 111 additions & 0 deletions src/Features/JsonPatch.SystemTextJson/src/Adapters/IObjectAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.JsonPatch.SystemTextJson.Operations;

namespace Microsoft.AspNetCore.JsonPatch.SystemTextJson.Adapters;

/// <summary>
/// Defines the operations that can be performed on a JSON patch document.
/// </summary>
public interface IObjectAdapter
{
/// <summary>
/// Using the "add" operation a new value is inserted into the root of the target
/// document, into the target array at the specified valid index, or to a target object at
/// the specified location.
///
/// When adding to arrays, the specified index MUST NOT be greater than the number of elements in the array.
/// To append the value to the array, the index of "-" character is used (see [RFC6901]).
///
/// When adding to an object, if an object member does not already exist, a new member is added to the object at the
/// specified location or if an object member does exist, that member's value is replaced.
///
/// The operation object MUST contain a "value" member whose content
/// specifies the value to be added.
///
/// For example:
///
/// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
///
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-4"/>
/// </summary>
/// <param name="operation">The add operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Add(Operation operation, object objectToApplyTo);

/// <summary>
/// Using the "copy" operation, a value is copied from a specified location to the
/// target location.
///
/// The operation object MUST contain a "from" member, which references the location in the
/// target document to copy the value from.
///
/// The "from" location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
///
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-7"/>
/// </summary>
/// <param name="operation">The copy operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Copy(Operation operation, object objectToApplyTo);

/// <summary>
/// Using the "move" operation the value at a specified location is removed and
/// added to the target location.
///
/// The operation object MUST contain a "from" member, which references the location in the
/// target document to move the value from.
///
/// The "from" location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
///
/// A location cannot be moved into one of its children.
///
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-6"/>
/// </summary>
/// <param name="operation">The move operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Move(Operation operation, object objectToApplyTo);

/// <summary>
/// Using the "remove" operation the value at the target location is removed.
///
/// The target location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "remove", "path": "/a/b/c" }
///
/// If removing an element from an array, any elements above the
/// specified index are shifted one position to the left.
///
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-6"/>
/// </summary>
/// <param name="operation">The remove operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Remove(Operation operation, object objectToApplyTo);

/// <summary>
/// Using the "replace" operation the value at the target location is replaced
/// with a new value. The operation object MUST contain a "value" member
/// which specifies the replacement value.
///
/// The target location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "replace", "path": "/a/b/c", "value": 42 }
///
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-6"/>
/// </summary>
/// <param name="operation">The replace operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Replace(Operation operation, object objectToApplyTo);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.JsonPatch.SystemTextJson.Operations;

namespace Microsoft.AspNetCore.JsonPatch.SystemTextJson.Adapters;

/// <summary>
/// Defines the operations that can be performed on a JSON patch document, including "test".
/// </summary>
public interface IObjectAdapterWithTest : IObjectAdapter
{
/// <summary>
/// Using the "test" operation a value at the target location is compared for
/// equality to a specified value.
///
/// The operation object MUST contain a "value" member that specifies
/// value to be compared to the target location's value.
///
/// The target location MUST be equal to the "value" value for the
/// operation to be considered successful.
///
/// For example:
/// { "op": "test", "path": "/a/b/c", "value": "foo" }
///
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-7"/>
/// </summary>
/// <param name="operation">The test operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Test(Operation operation, object objectToApplyTo);
}
Loading
Loading