Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
18 changes: 11 additions & 7 deletions src/JsonPatchGenerator/DefaultJsonPatchGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ namespace Firebend.JsonPatch;
public class DefaultJsonPatchGenerator : IJsonPatchGenerator
{
private readonly IJsonDiffDetector _diffDetector;
private readonly IJsonPatchWriter _writer;
private readonly Func<IJsonPatchWriter> _writerFactory;
private readonly IJsonDiffSettingsProvider _settings;
public DefaultJsonPatchGenerator(IJsonDiffDetector diffDetector, IJsonPatchWriter writer, IJsonDiffSettingsProvider settings)
public DefaultJsonPatchGenerator(IJsonDiffDetector diffDetector, Func<IJsonPatchWriter> writerFactory, IJsonDiffSettingsProvider settings)
{
_diffDetector = diffDetector;
_writer = writer;
_writerFactory = writerFactory;
_settings = settings;
}

Expand All @@ -40,27 +40,31 @@ public JsonPatchDocument<T> Generate<T>(T original, T modified)

var diffs = _diffDetector.DetectChanges(original, modified);

if (!diffs.Any()) { return new(); }

var writer = _writerFactory();

foreach (var jsonDiff in diffs)
{
switch (jsonDiff.Change)
{
case JsonChange.Unknown:
break;
case JsonChange.Add:
_writer.WriteAdd(jsonDiff.Path, jsonDiff.Value);
writer.WriteAdd(jsonDiff.Path, jsonDiff.Value);
break;
case JsonChange.Replace:
_writer.WriteReplace(jsonDiff.Path, jsonDiff.Value);
writer.WriteReplace(jsonDiff.Path, jsonDiff.Value);
break;
case JsonChange.Remove:
_writer.WriteRemove(jsonDiff.Path);
writer.WriteRemove(jsonDiff.Path);
break;
default:
throw new ArgumentOutOfRangeException();
}
}

var patchJson = _writer.Finish();
var patchJson = writer.Finish();

if (string.IsNullOrWhiteSpace(patchJson))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ public static IServiceCollection AddJsonPatchGenerator(this IServiceCollection c

collection.TryAddSingleton<IJsonDiffSettingsProvider>(new JsonDiffSettingsProvider(settings));
collection.TryAddTransient<IJsonPatchWriter, JsonPatchWriter>();
collection.TryAddTransient<IJsonPatchGenerator, DefaultJsonPatchGenerator>();
collection.TryAddTransient<IJsonPatchGenerator>(sp =>
new DefaultJsonPatchGenerator(sp.GetRequiredService<IJsonDiffDetector>(),
sp.GetRequiredService<IJsonPatchWriter>,
sp.GetRequiredService<IJsonDiffSettingsProvider>()));
collection.TryAddTransient<IJsonDiffDetector, JsonDiffDetector>();

return collection;
Expand Down
36 changes: 36 additions & 0 deletions tests/JsonPatchGenerator.Tests/JsonPatchGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System.Threading.Tasks;

// ReSharper disable UnusedAutoPropertyAccessor.Local

Expand Down Expand Up @@ -620,6 +621,41 @@ public void Json_Patch_Generator_Should_Handle_Multiple_Generations()
patchWithNoChanges.Operations.Should().BeEmpty();
}

[TestMethod]
public async Task Json_Patch_Document_Generator_Should_Be_Thread_Safe()
{
//arrange
var generator = CreateGenerator();

var a1 = new Agent { FirstName = "A" };
var b1 = new Agent { FirstName = "B" };

var a2 = new Agent { LastName = "C" };
var b2 = new Agent { LastName = "D" };

//act
var task1 = Task.Run(() => generator.Generate(a1, b1));
var task2 = Task.Run(() => generator.Generate(a2, b2));

await Task.WhenAll(task1, task2);

//assert
var patch1 = await task1;
var patch2 = await task2;

patch1.Operations.Should().HaveCount(1);
var op1 = patch1.Operations[0];
op1.op.Should().Be("replace");
op1.path.Should().Be("/FirstName");
op1.value.Should().Be("B");

patch2.Operations.Should().HaveCount(1);
var op2 = patch2.Operations[0];
op2.op.Should().Be("replace");
op2.path.Should().Be("/LastName");
op2.value.Should().Be("D");
}

private static JsonSerializerSettings CreateCustomSettings()
{
var serializerSettings = new JsonSerializerSettings
Expand Down