This library contains Json Patch implementation using Newtonsoft.Json.
The library supports two modes. In the first one you can patch JToken
objects using PatchTokenCopy
method:
var input = JToken.Parse("{ \"age\": 40 }");
var output = JsonPatcher.PatchTokenCopy(
input,
new[]
{
new JsonPatchReplaceOperation
{
Path = "/age",
Value = 41
}
});
output.ShouldBeJson("{ \"age\": 41 }");
In the second mode you can patch POCO objects using PatchObjectCopy
method:
var input = new Person
{
Name = "Andrey"
};
var output = JsonPatcher.PatchObjectCopy(
input,
new[]
{
new JsonPatchAddOperation
{
Path = "/Name",
Value = "Ivan"
}
});
output.Name.ShouldBe("Ivan");
Be aware, that the library never modifies input object.
In JsonPatch
library, you can use POCO objects in two places. First of all, you can patch them, as you saw in the previous example. But also you can use them as values of patch operations:
var patchOperation = new JsonPatchAddOperation
{
Path = "/-",
Value = new PersonData("Ivan", 40)
};
In both cases, it is quite possible that your objects can contain custom serializations settings. You can respect these settings by passing either JsonSerializer
or JsonSerializerSettings
object into PatchTokenCopy
and PatchObjectCopy
methods:
var input = JToken.Parse("[]");
var serializer = JsonSerializer.Create(GetSerializerSettingsForPersonData());
var output = JsonPatcher.PatchTokenCopy(
input,
new[]
{
new JsonPatchAddOperation
{
Path = "/-",
Value = new PersonData("Ivan", 40)
}
},
serializer);
JToken.DeepEquals(
JToken.Parse("[{\"name\":\"Ivan\",\"age\":40}]"),
output
).ShouldBeTrue();
Json Patch specification says that patching should stop on any error. And this is a default behaviour of the library. In case any operation can't be fulfilled, JsonPatchException
exception will be thrown.
But you can customize this behavior. Almost every class of patch operation contains ErrorHandlingType
property.
var patch = new JsonPatchMoveOperation
{
Path = "/bar",
From = "/foo",
ErrorHandlingType = ErrorHandlingTypes.Skip
};
This property can have one of the following values:
null
. Default. In this case, if the patch can't be applied default error handling behavior will be applied. Read about it later.Skip
. In this case, if the patch can't be applied, nothing happens and the next patch will be processed.Throw
. In this case, if the patch can't be applied aJsonPatchException
exception will be thrown.
Be aware, that JsonPatchTestOperation
does not have this property. If the test is failed, an exception will always be thrown.
You can set default error handling behavior by setting globalErrorHandling
parameter in the PatchTokenCopy
and PatchObjectCopy
methods of JsonPatcher
class:
var output = JsonPatcher.PatchObjectCopy(
input,
new[]
{
new JsonPatchReplaceOperation
{
Path = "/xxx",
Value = 41
}
},
serializationSettings,
globalErrorHandling: ErrorHandlingTypes.Skip);
Json Patch specification provides 6 patch operations:
Add
Move
Replace
Remove
Test
Copy
All of them are supported in the library. But the library provides one more additional operation: AddMany
. For this operation 'Path' property must point to a place in an array. Value
property may be anything. But if it is an array, then each value of this array will be inserted into the Path
array.
Here is the difference between Add
and AddMany
operations. Let's say we want to patch JSON [1, 2, 3]
. In the case of Add
operation:
{
"op": "add",
"path": "/-",
"value": [4, 5, 6]
}
result will be [1, 2, 3, [4, 5, 6]]
. But in the case of 'AddMany' operation:
{
"op": "addmany",
"path": "/-",
"value": [4, 5, 6]
}
result will be [1, 2, 3, 4, 5, 6]
.