diff --git a/README.md b/README.md index 6c7ac0f..cce8e87 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# JSON Merge Patch support for ASP.NET Core +# JSON Merge Patch support for ASP.NET Core 2, 3 and 5 -[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch) - [Morcatko.AspNetCore.JsonMergePatch](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch) (ASP.NET Core 2.x) -[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson) - [Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson) (ASP.NET Core 3.x) -[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.SystemText.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.SystemText) - [Morcatko.AspNetCore.JsonMergePatch.SystemText](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.SystemText) (ASP.NET Core 3.x) -[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.Document.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.Document) - [Morcatko.AspNetCore.JsonMergePatch.Document](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.Document) (ASP.NET Core 3.x - base package) +[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch) - [Morcatko.AspNetCore.JsonMergePatch](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch) (ASP.NET Core 2) +[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson) - [Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson) (ASP.NET Core 3 & 5) +[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.SystemText.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.SystemText) - [Morcatko.AspNetCore.JsonMergePatch.SystemText](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.SystemText) (ASP.NET Core 3 & 5) +[![Nuget](https://img.shields.io/nuget/v/Morcatko.AspNetCore.JsonMergePatch.Document.svg)](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.Document) - [Morcatko.AspNetCore.JsonMergePatch.Document](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.Document) (ASP.NET Core 3 & 5 - base package) ### JSON Merge Patch - [RFC 7396](https://tools.ietf.org/html/rfc7396) @@ -36,9 +36,9 @@ resulting C# object: ### How to See `2.1-testApp` or `3.0 testApp` for sample 1. Install nuget. -- ASP.NET Core 2.x [Morcatko.AspNetCore.JsonMergePatch](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch) -- ASP.NET Core 3.x (Newtonsoft.Json) [Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson) -- ASP.NET Core 3.x (System.Text) [Morcatko.AspNetCore.JsonMergePatch.SystemText](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.SystemText) nuget +- ASP.NET Core 2 [Morcatko.AspNetCore.JsonMergePatch](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch) +- ASP.NET Core 3 & 5 (Newtonsoft.Json) [Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson) +- ASP.NET Core 3 & 5 (System.Text) [Morcatko.AspNetCore.JsonMergePatch.SystemText](https://www.nuget.org/packages/Morcatko.AspNetCore.JsonMergePatch.SystemText) nuget 2. Add to your startup class ``` @@ -49,9 +49,9 @@ public void ConfigureServices(IServiceCollection services) ... services .AddMvc() // or .AddMvcCore() - //.AddJsonMergePatch(); // 2.x - //.AddNewtonsoftJsonMergePatch(); // 3.x (Newtonsoft.Josn) - //.AddSystemTextJsonMergePatch(); // 3.x (System.Text) + //.AddJsonMergePatch(); // 2 + //.AddNewtonsoftJsonMergePatch(); // 3 & 5 (Newtonsoft.Josn) + //.AddSystemTextJsonMergePatch(); // 3 & 5 (System.Text) ... } ``` @@ -78,8 +78,8 @@ patch.ApplyToT(backendModel) 4. Swagger config (optional) copy & paste this class into your app - - 2.x - https://github.com/Morcatko/Morcatko.AspNetCore.JsonMergePatch/blob/master/src/2.1-testApp/JsonMergePatchDocumentOperationFilter.cs - - 3.x - https://github.com/Morcatko/Morcatko.AspNetCore.JsonMergePatch/blob/master/src/3.0-testApp/JsonMergePatchDocumentOperationFilter.cs + - 2 - https://github.com/Morcatko/Morcatko.AspNetCore.JsonMergePatch/blob/master/src/2.1-testApp/JsonMergePatchDocumentOperationFilter.cs + - 3 & 5 - https://github.com/Morcatko/Morcatko.AspNetCore.JsonMergePatch/blob/master/src/3.0-testApp/JsonMergePatchDocumentOperationFilter.cs ``` services.AddSwaggerGen(c => { diff --git a/src/3.0-JsonMergePatch.SystemText/Builders/PatchBuilder.cs b/src/3.0-JsonMergePatch.SystemText/Builders/PatchBuilder.cs index e4f55b3..0578eaa 100644 --- a/src/3.0-JsonMergePatch.SystemText/Builders/PatchBuilder.cs +++ b/src/3.0-JsonMergePatch.SystemText/Builders/PatchBuilder.cs @@ -1,5 +1,6 @@ using Morcatko.AspNetCore.JsonMergePatch.Internal; using System; +using System.Linq; using System.Reflection; using System.Text.Json; @@ -14,25 +15,23 @@ private static object ToObject(this JsonElement jsonElement) case JsonValueKind.Null: return null; case JsonValueKind.String: return jsonElement.GetString(); case JsonValueKind.Number: return jsonElement.GetGenericNumber(); + case JsonValueKind.Array: return jsonElement.EnumerateArray().Select(j => j.ToObject()).ToArray(); case JsonValueKind.True: return true; case JsonValueKind.False: return false; case JsonValueKind.Undefined: case JsonValueKind.Object: - case JsonValueKind.Array: default: throw new NotSupportedException($"Unsupported ValueKind - {jsonElement.ValueKind}"); } } - private static object GetGenericNumber (this JsonElement jsonElement) - { - - // Attempt to parse the JSON Element as an Int32 first - if (jsonElement.TryGetInt32(out int int32)) return int32; - - // Failing that, parse it as a Decimal instead - return jsonElement.GetDecimal(); - + private static object GetGenericNumber(this JsonElement jsonElement) + { + // Attempt to parse the JSON Element as an Int32 first + if (jsonElement.TryGetInt32(out int int32)) return int32; + + // Failing that, parse it as a Decimal instead + return jsonElement.GetDecimal(); } private static bool IsValue(this JsonValueKind valueKind) diff --git a/src/3.0-JsonMergePatch.Tests/Integration/MvcTest.cs b/src/3.0-JsonMergePatch.Tests/Integration/MvcTest.cs index a0a5b0b..7de21dd 100644 --- a/src/3.0-JsonMergePatch.Tests/Integration/MvcTest.cs +++ b/src/3.0-JsonMergePatch.Tests/Integration/MvcTest.cs @@ -123,7 +123,8 @@ await p.MergePatchAsync(null, new[] [MemberData(nameof(GetCombinations))] public async Task NullableDecimalFloatingPoint(bool core, bool newtonsoft) { - using (var p = new TestHelper(core, newtonsoft)) { + using (var p = new TestHelper(core, newtonsoft)) + { await p.PostAsync("0", p.GetTestModel()); await p.MergePatchAsync(null, new[] @@ -133,11 +134,31 @@ await p.MergePatchAsync(null, new[] var patchedModel = await p.GetAsync("0"); var expected = p.GetTestModel(); - expected.NullableDecimal = (decimal?) 7.5; + expected.NullableDecimal = (decimal?)7.5; Assert.Equal(expected, patchedModel); } } + [Theory] + [MemberData(nameof(GetCombinations))] + public async Task Arrays(bool core, bool newtonsoft) + { + using (var p = new TestHelper(core, newtonsoft)) + { + await p.PostAsync("0", p.GetTestModel()); + + await p.MergePatchAsync(null, new[] + { + new { id = 0, ArrayOfFloats = new [] { 7, 3.5f }} + }); + + var patchedModel = await p.GetAsync("0"); + var expected = p.GetTestModel(); + expected.ArrayOfFloats = new [] { 7, 3.5f }; + Assert.Equal(expected, patchedModel); + } + } + [Theory(Skip = "Does not work")] [MemberData(nameof(GetCombinations))] public async Task MissingRequiredProperty(bool core, bool newtonsoft) @@ -152,8 +173,8 @@ public async Task MissingRequiredProperty(bool core, bool newtonsoft) expected.Integer = 8; Assert.Equal(expected, patchedModel); } - } - + } + #region ValueEnum [Theory(Skip = "Enums do not work - https://github.com/aspnet/Home/issues/2423")] [MemberData(nameof(GetCombinations))] diff --git a/src/3.0-JsonMergePatch.Tests/TestModel.cs b/src/3.0-JsonMergePatch.Tests/TestModel.cs index 10c9f18..d3f6b7a 100644 --- a/src/3.0-JsonMergePatch.Tests/TestModel.cs +++ b/src/3.0-JsonMergePatch.Tests/TestModel.cs @@ -29,6 +29,8 @@ public class TestModelBase : IEquatable, IEquatable SubModels { get; set; } = new Dictionary(); public bool Equals(TestModelBase other) @@ -43,7 +45,8 @@ public bool Equals(TestModelBase other) && this.ValueEnum == other.ValueEnum && this.NullableDecimal == other.NullableDecimal && this.Date == other.Date - && this.Date.GetValueOrDefault().Offset == other.Date.GetValueOrDefault().Offset + && this.Date.GetValueOrDefault().Offset == other.Date.GetValueOrDefault().Offset + && Enumerable.SequenceEqual(this.ArrayOfFloats, other.ArrayOfFloats) && Enumerable.SequenceEqual(this.SubModels?.Keys, other.SubModels?.Keys) && Enumerable.SequenceEqual(this.SubModels?.Values, other.SubModels?.Values) && ((this.SubModel == other.SubModel)