diff --git a/CHANGELOG.md b/CHANGELOG.md index c796425..9e61ec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 2.0.0 - JsonPatchDocument types now adds required converters using JsonConverterAttribute and converters no longer need to be set manually to JsonSerializerOptions https://github.com/Havunen/SystemTextJsonPatch/issues/18 - netstandard2.0 target now depends on System.Text.Json v7 +- Small performance optimizations ## 1.2.0 - Better support for patching arrays by index https://github.com/Havunen/SystemTextJsonPatch/issues/15 diff --git a/README.md b/README.md index fb0e60d..9d641d8 100644 --- a/README.md +++ b/README.md @@ -60,16 +60,16 @@ This test deserializes a JSON patch document of 8 operations and applies the cha See [SystemTextJsonPatch.Benchmark](https://github.com/Havunen/SystemTextJsonPatch/tree/main/SystemTextJsonPatch.Benchmark) for more details. -BenchmarkDotNet=v0.13.2, OS=Windows 11 (10.0.22000.978/21H2) +BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22621.1413/22H2/2022Update/SunValley2) AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores -.NET SDK=7.0.100-rc.1.22431.12 - [Host] : .NET 6.0.9 (6.0.922.41905), X64 RyuJIT AVX2 - Job-URORCR : .NET 6.0.9 (6.0.922.41905), X64 RyuJIT AVX2 +.NET SDK=7.0.300-preview.23122.5 + [Host] : .NET 7.0.3 (7.0.323.6910), X64 RyuJIT AVX2 + Job-STVRTF : .NET 7.0.3 (7.0.323.6910), X64 RyuJIT AVX2 WarmupCount=2 -| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated | -|-------------------- |-----------:|----------:|----------:|-------:|-------:|----------:| -| SystemTextJsonPatch | 7.233 us | 0.0381 us | 0.0356 us | 0.3738 | - | 6.16 KB | -| MarvinJsonPatch | 979.525 us | 9.9310 us | 8.8036 us | 5.8594 | 3.9063 | 98.13 KB | -| AspNetCoreJsonPatch | 26.645 us | 0.2023 us | 0.1892 us | 2.5940 | 0.0610 | 42.49 KB | +| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated | +|-------------------- |-----------:|-----------:|-----------:|-------:|-------:|----------:| +| SystemTextJsonPatch | 6.579 us | 0.0537 us | 0.0476 us | 0.3433 | - | 5.69 KB | +| MarvinJsonPatch | 913.023 us | 14.2077 us | 16.9133 us | 5.8594 | 3.9063 | 96.02 KB | +| AspNetCoreJsonPatch | 24.543 us | 0.2470 us | 0.2310 us | 2.6550 | 0.0610 | 43.61 KB | diff --git a/SystemTextJsonPatch/Internal/ConversionResultProvider.cs b/SystemTextJsonPatch/Internal/ConversionResultProvider.cs index 89bb99e..4ae99a9 100644 --- a/SystemTextJsonPatch/Internal/ConversionResultProvider.cs +++ b/SystemTextJsonPatch/Internal/ConversionResultProvider.cs @@ -160,7 +160,11 @@ private static bool TryConvertDecimalToNumber(decimal decimalValue, Type typeToC private static object? Deserialize(object? value, Type typeToConvertTo, JsonSerializerOptions options) { - if (typeToConvertTo == typeof(JsonNode)) + if (typeToConvertTo == typeof(JsonElement)) + { + return JsonSerializer.SerializeToElement(value, options); + } + if (typeToConvertTo == typeof(JsonNode)) { return JsonSerializer.SerializeToNode(value, options); } @@ -168,12 +172,21 @@ private static bool TryConvertDecimalToNumber(decimal decimalValue, Type typeToC { return JsonSerializer.SerializeToDocument(value, options); } - if (typeToConvertTo == typeof(JsonElement)) - { - return JsonSerializer.SerializeToElement(value, options); - } - return JsonSerializer.Deserialize(JsonSerializer.Serialize(value, options), typeToConvertTo, options); + if (value is JsonElement jsonEl) + { + return JsonSerializer.Deserialize(jsonEl, typeToConvertTo, options); + } + if (value is JsonNode jsonNode) + { + return JsonSerializer.Deserialize(jsonNode, typeToConvertTo, options); + } + if (value is JsonDocument jsonDoc) + { + return JsonSerializer.Deserialize(jsonDoc, typeToConvertTo, options); + } + + return JsonSerializer.Deserialize(JsonSerializer.SerializeToUtf8Bytes(value, options), typeToConvertTo, options); } private static bool IsNullableType(Type type) diff --git a/SystemTextJsonPatch/Internal/ParsedPath.cs b/SystemTextJsonPatch/Internal/ParsedPath.cs index b7a5ea6..78d1b1b 100644 --- a/SystemTextJsonPatch/Internal/ParsedPath.cs +++ b/SystemTextJsonPatch/Internal/ParsedPath.cs @@ -46,7 +46,9 @@ private static string[] ParsePath(string path) for (var i = 0; i < path.Length; i++) { - if (path[i] == '/') + var c = path[i]; + + if (c == '/') { if (sb.Length > 0) { @@ -54,19 +56,20 @@ private static string[] ParsePath(string path) sb.Length = 0; } } - else if (path[i] == '~') + else if (c == '~') { ++i; - if (i >= path.Length) + c = path[i]; + if (i >= path.Length) { throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null); } - if (path[i] == '0') + if (c == '0') { sb.Append('~'); } - else if (path[i] == '1') + else if (c == '1') { sb.Append('/'); } @@ -77,7 +80,7 @@ private static string[] ParsePath(string path) } else { - sb.Append(path[i]); + sb.Append(c); } }