Skip to content

Commit fbf3001

Browse files
author
Sampo Kivistö
committed
Initial implementation based on Microsoft.AspNetCore.JsonPatch 6.0.5
0 parents  commit fbf3001

File tree

71 files changed

+9770
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+9770
-0
lines changed

.gitignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
*.swp
2+
*.*~
3+
project.lock.json
4+
.DS_Store
5+
*.pyc
6+
nupkg/
7+
8+
# Visual Studio Code
9+
.vscode
10+
11+
# Rider
12+
.idea
13+
14+
# User-specific files
15+
*.suo
16+
*.user
17+
*.userosscache
18+
*.sln.docstates
19+
20+
# Build results
21+
[Dd]ebug/
22+
[Dd]ebugPublic/
23+
[Rr]elease/
24+
[Rr]eleases/
25+
x64/
26+
x86/
27+
build/
28+
bld/
29+
[Bb]in/
30+
[Oo]bj/
31+
[Oo]ut/
32+
msbuild.log
33+
msbuild.err
34+
msbuild.wrn
35+
36+
# Visual Studio 2015
37+
.vs/

SystemTextJsonPatch.sln

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.2.32505.173
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemTextJsonPatch", "src\SystemTextJsonPatch.csproj", "{245FB7D6-88EC-4898-B3FE-D79A0DF26B5E}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemTextJsonPatch.Tests", "test\SystemTextJsonPatch.Tests.csproj", "{BE6578FD-27B1-44EF-974A-C36DD8DA3B08}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{245FB7D6-88EC-4898-B3FE-D79A0DF26B5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{245FB7D6-88EC-4898-B3FE-D79A0DF26B5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{245FB7D6-88EC-4898-B3FE-D79A0DF26B5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{245FB7D6-88EC-4898-B3FE-D79A0DF26B5E}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{BE6578FD-27B1-44EF-974A-C36DD8DA3B08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{BE6578FD-27B1-44EF-974A-C36DD8DA3B08}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{BE6578FD-27B1-44EF-974A-C36DD8DA3B08}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{BE6578FD-27B1-44EF-974A-C36DD8DA3B08}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {E2351186-FE78-4401-AD58-1B769DC4C98A}
30+
EndGlobalSection
31+
EndGlobal

src/Adapters/AdapterFactory.cs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Collections;
6+
using SystemTextJsonPatch.Internal;
7+
using Newtonsoft.Json.Linq;
8+
using Newtonsoft.Json.Serialization;
9+
10+
namespace SystemTextJsonPatch.Adapters;
11+
12+
/// <summary>
13+
/// The default AdapterFactory to be used for resolving <see cref="IAdapter"/>.
14+
/// </summary>
15+
public class AdapterFactory : IAdapterFactory
16+
{
17+
internal static AdapterFactory Default { get; } = new();
18+
19+
/// <inheritdoc />
20+
#pragma warning disable PUB0001
21+
public virtual IAdapter Create(object target, IContractResolver contractResolver)
22+
#pragma warning restore PUB0001
23+
{
24+
if (target == null)
25+
{
26+
throw new ArgumentNullException(nameof(target));
27+
}
28+
29+
if (contractResolver == null)
30+
{
31+
throw new ArgumentNullException(nameof(contractResolver));
32+
}
33+
34+
var jsonContract = contractResolver.ResolveContract(target.GetType());
35+
36+
if (target is JObject)
37+
{
38+
return new JObjectAdapter();
39+
}
40+
if (target is IList)
41+
{
42+
return new ListAdapter();
43+
}
44+
else if (jsonContract is JsonDictionaryContract jsonDictionaryContract)
45+
{
46+
var type = typeof(DictionaryAdapter<,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType);
47+
return (IAdapter)Activator.CreateInstance(type);
48+
}
49+
else if (jsonContract is JsonDynamicContract)
50+
{
51+
return new DynamicObjectAdapter();
52+
}
53+
else
54+
{
55+
return new PocoAdapter();
56+
}
57+
}
58+
}
59+

src/Adapters/IAdapterFactory.cs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using SystemTextJsonPatch.Internal;
5+
using Newtonsoft.Json.Serialization;
6+
7+
namespace SystemTextJsonPatch.Adapters;
8+
9+
/// <summary>
10+
/// Defines the operations used for loading an <see cref="IAdapter"/> based on the current object and ContractResolver.
11+
/// </summary>
12+
public interface IAdapterFactory
13+
{
14+
/// <summary>
15+
/// Creates an <see cref="IAdapter"/> for the current object
16+
/// </summary>
17+
/// <param name="target">The target object</param>
18+
/// <param name="contractResolver">The current contract resolver</param>
19+
/// <returns>The needed <see cref="IAdapter"/></returns>
20+
#pragma warning disable PUB0001
21+
IAdapter Create(object target, IContractResolver contractResolver);
22+
#pragma warning restore PUB0001
23+
}

src/Adapters/IObjectAdapter.cs

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using SystemTextJsonPatch.Operations;
5+
6+
namespace SystemTextJsonPatch.Adapters;
7+
8+
/// <summary>
9+
/// Defines the operations that can be performed on a JSON patch document.
10+
/// </summary>
11+
public interface IObjectAdapter
12+
{
13+
/// <summary>
14+
/// Using the "add" operation a new value is inserted into the root of the target
15+
/// document, into the target array at the specified valid index, or to a target object at
16+
/// the specified location.
17+
///
18+
/// When adding to arrays, the specified index MUST NOT be greater than the number of elements in the array.
19+
/// To append the value to the array, the index of "-" character is used (see [RFC6901]).
20+
///
21+
/// When adding to an object, if an object member does not already exist, a new member is added to the object at the
22+
/// specified location or if an object member does exist, that member's value is replaced.
23+
///
24+
/// The operation object MUST contain a "value" member whose content
25+
/// specifies the value to be added.
26+
///
27+
/// For example:
28+
///
29+
/// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
30+
///
31+
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-4"/>
32+
/// </summary>
33+
/// <param name="operation">The add operation.</param>
34+
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
35+
void Add(Operation operation, object objectToApplyTo);
36+
37+
/// <summary>
38+
/// Using the "copy" operation, a value is copied from a specified location to the
39+
/// target location.
40+
///
41+
/// The operation object MUST contain a "from" member, which references the location in the
42+
/// target document to copy the value from.
43+
///
44+
/// The "from" location MUST exist for the operation to be successful.
45+
///
46+
/// For example:
47+
///
48+
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
49+
///
50+
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-7"/>
51+
/// </summary>
52+
/// <param name="operation">The copy operation.</param>
53+
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
54+
void Copy(Operation operation, object objectToApplyTo);
55+
56+
/// <summary>
57+
/// Using the "move" operation the value at a specified location is removed and
58+
/// added to the target location.
59+
///
60+
/// The operation object MUST contain a "from" member, which references the location in the
61+
/// target document to move the value from.
62+
///
63+
/// The "from" location MUST exist for the operation to be successful.
64+
///
65+
/// For example:
66+
///
67+
/// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
68+
///
69+
/// A location cannot be moved into one of its children.
70+
///
71+
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-6"/>
72+
/// </summary>
73+
/// <param name="operation">The move operation.</param>
74+
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
75+
void Move(Operation operation, object objectToApplyTo);
76+
77+
/// <summary>
78+
/// Using the "remove" operation the value at the target location is removed.
79+
///
80+
/// The target location MUST exist for the operation to be successful.
81+
///
82+
/// For example:
83+
///
84+
/// { "op": "remove", "path": "/a/b/c" }
85+
///
86+
/// If removing an element from an array, any elements above the
87+
/// specified index are shifted one position to the left.
88+
///
89+
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-6"/>
90+
/// </summary>
91+
/// <param name="operation">The remove operation.</param>
92+
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
93+
void Remove(Operation operation, object objectToApplyTo);
94+
95+
/// <summary>
96+
/// Using the "replace" operation the value at the target location is replaced
97+
/// with a new value. The operation object MUST contain a "value" member
98+
/// which specifies the replacement value.
99+
///
100+
/// The target location MUST exist for the operation to be successful.
101+
///
102+
/// For example:
103+
///
104+
/// { "op": "replace", "path": "/a/b/c", "value": 42 }
105+
///
106+
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-6"/>
107+
/// </summary>
108+
/// <param name="operation">The replace operation.</param>
109+
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
110+
void Replace(Operation operation, object objectToApplyTo);
111+
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using SystemTextJsonPatch.Operations;
5+
6+
namespace SystemTextJsonPatch.Adapters;
7+
8+
/// <summary>
9+
/// Defines the operations that can be performed on a JSON patch document, including "test".
10+
/// </summary>
11+
public interface IObjectAdapterWithTest : IObjectAdapter
12+
{
13+
/// <summary>
14+
/// Using the "test" operation a value at the target location is compared for
15+
/// equality to a specified value.
16+
///
17+
/// The operation object MUST contain a "value" member that specifies
18+
/// value to be compared to the target location's value.
19+
///
20+
/// The target location MUST be equal to the "value" value for the
21+
/// operation to be considered successful.
22+
///
23+
/// For example:
24+
/// { "op": "test", "path": "/a/b/c", "value": "foo" }
25+
///
26+
/// See RFC 6902 <see href="https://tools.ietf.org/html/rfc6902#page-7"/>
27+
/// </summary>
28+
/// <param name="operation">The test operation.</param>
29+
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
30+
void Test(Operation operation, object objectToApplyTo);
31+
}

0 commit comments

Comments
 (0)