From 8999f7b97a34253a4b5269c2abe2914d74238438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrico=20M=C3=BCller?= Date: Wed, 23 Oct 2024 14:12:28 +0200 Subject: [PATCH 1/3] using System.Text.Json instead of Newtonsoft.Json --- .../RiskFirst.Hateoas.BasicSample/Program.cs | 1 - .../LinksTests.cs | 71 ++++++++----------- .../Program.cs | 3 +- .../LinkTests.cs | 8 +-- src/RiskFirst.Hateoas.Models/Link.cs | 2 +- .../LinkCollection.cs | 4 +- .../LinkCollectionConverter.cs | 19 ++--- src/RiskFirst.Hateoas.Models/LinkContainer.cs | 7 +- .../RiskFirst.Hateoas.Models.csproj | 9 +-- .../JsonSerializationTests.cs | 12 ++-- 10 files changed, 62 insertions(+), 74 deletions(-) diff --git a/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/Program.cs b/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/Program.cs index 254a4a6..c7c8665 100644 --- a/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/Program.cs +++ b/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/Program.cs @@ -12,7 +12,6 @@ private static void Main(string[] args) var services = builder.Services; services.AddControllers() - .AddNewtonsoftJson() .AddXmlSerializerFormatters(); services.AddScoped(); services.AddLinks(config => diff --git a/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/LinksTests.cs b/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/LinksTests.cs index 371b41a..d4ef292 100644 --- a/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/LinksTests.cs +++ b/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/LinksTests.cs @@ -1,14 +1,12 @@ using System.Net.Http.Headers; using System.Xml.Serialization; using Microsoft.AspNetCore.Mvc.Testing; -using Newtonsoft.Json; using RiskFirst.Hateoas.BasicSample.Models; using RiskFirst.Hateoas.Models; namespace RiskFirst.Hateoas.BasicSample.Tests; -public class BasicTests - : IClassFixture> +public class BasicTests : IClassFixture> { private readonly WebApplicationFactory _factory; @@ -24,13 +22,12 @@ public async Task GetAllValues_Json_ReturnsObjectsWithLinks() var client = _factory.CreateClient(); // Act - var response = await client.GetAsync("/api/values"); - response.EnsureSuccessStatusCode(); + var values = await client.GetFromJsonAsync>("/api/values"); - var responseString = await response.Content.ReadAsStringAsync(); - var values = JsonConvert.DeserializeObject>(responseString); + // Assert + var items = values?.Items ?? Enumerable.Empty(); - Assert.All(values.Items, i => Assert.True(i.Links.Count > 0, "Invalid number of links")); + Assert.All(items, i => Assert.True(i.Links.Count > 0, "Invalid number of links")); } [Fact] @@ -41,13 +38,14 @@ public async Task GetAllValues_Xml_ReturnsObjectsWithLinks() // Act client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); - var response = await client.GetAsync("/api/values"); - response.EnsureSuccessStatusCode(); + var responseString = await client.GetStringAsync("/api/values"); - var responseString = await response.Content.ReadAsStringAsync(); var values = DeserializeXml>(responseString); - Assert.All(values.Items, i => Assert.True(i.Links.Count > 0, "Invalid number of links")); + // Assert + var items = values?.Items ?? Enumerable.Empty(); + + Assert.All(items, i => Assert.True(i.Links.Count > 0, "Invalid number of links")); } [Fact] @@ -56,14 +54,13 @@ public async Task GetValue_Json_AlternateRoute_ReturnsObjectsWithLinks() // Arrange var client = _factory.CreateClient(); - // Act - var response = await client.GetAsync("/api/values/v2/1"); - response.EnsureSuccessStatusCode(); + var test = await client.GetStringAsync("/api/values/v2/1"); - var responseString = await response.Content.ReadAsStringAsync(); - var value = JsonConvert.DeserializeObject(responseString); + // Act + var value = await client.GetFromJsonAsync("/api/values/v2/1"); - Assert.True(value.Links.Count > 0, "Invalid number of links"); + // Assert + Assert.True(value?.Links.Count > 0, "Invalid number of links"); } [Fact] @@ -74,13 +71,12 @@ public async Task GetValue_Xml_AlternateRoute_ReturnsObjectsWithLinks() // Act client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); - var response = await client.GetAsync("/api/values/v2/1"); - response.EnsureSuccessStatusCode(); + var responseString = await client.GetStringAsync("/api/values/v2/1"); - var responseString = await response.Content.ReadAsStringAsync(); var value = DeserializeXml(responseString); - Assert.True(value.Links.Count > 0, "Invalid number of links"); + // Assert + Assert.True(value?.Links.Count > 0, "Invalid number of links"); } [Fact] @@ -89,14 +85,11 @@ public async Task GetValue_Json_ReturnsObjectsWithLinks() // Arrange var client = _factory.CreateClient(); - // Act - var response = await client.GetAsync("/api/values/1"); - response.EnsureSuccessStatusCode(); - - var responseString = await response.Content.ReadAsStringAsync(); - var value = JsonConvert.DeserializeObject(responseString); + // Value + var value = await client.GetFromJsonAsync("/api/values/1"); - Assert.True(value.Links.Count > 0, "Invalid number of links"); + // Assert + Assert.True(value?.Links.Count > 0, "Invalid number of links"); } [Fact] @@ -107,21 +100,19 @@ public async Task GetValue_Xml_ReturnsObjectsWithLinks() // Act client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); - var response = await client.GetAsync("/api/values/1"); - response.EnsureSuccessStatusCode(); + var responseString = await client.GetStringAsync("/api/values/1"); - var responseString = await response.Content.ReadAsStringAsync(); var value = DeserializeXml(responseString); - Assert.True(value.Links.Count > 0, "Invalid number of links"); + // Assert + Assert.True(value?.Links.Count > 0, "Invalid number of links"); } - private static T DeserializeXml(string xml) + private static T? DeserializeXml(string xml) { - using (var reader = new StringReader(xml)) - { - var serializer = new XmlSerializer(typeof(T)); - return (T)serializer.Deserialize(reader); - } + using var reader = new StringReader(xml); + + var serializer = new XmlSerializer(typeof(T)); + return (T?)serializer.Deserialize(reader); } -} +} \ No newline at end of file diff --git a/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/Program.cs b/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/Program.cs index d45e01a..2faeadd 100644 --- a/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/Program.cs +++ b/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/Program.cs @@ -13,8 +13,7 @@ private static void Main(string[] args) var services = builder.Services; - services.AddControllers() - .AddNewtonsoftJson(); + services.AddControllers(); services.AddTransient(); services.AddScoped(); diff --git a/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/LinkTests.cs b/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/LinkTests.cs index c107096..8bc68b0 100644 --- a/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/LinkTests.cs +++ b/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/LinkTests.cs @@ -1,8 +1,8 @@ using Microsoft.AspNetCore.Mvc.Testing; -using Newtonsoft.Json; using RiskFirst.Hateoas.CustomRequirementSample.Models; using RiskFirst.Hateoas.CustomRequirementsSample.Tests; using RiskFirst.Hateoas.Models; +using System.Net.Http.Json; namespace RiskFirst.Hateoas.CustomRequirementsSample.TestsNew; @@ -23,11 +23,9 @@ public async Task GetAllValues_Json_ReturnsLinksWithRootApi() var client = _factory.CreateClient(); // Act - var response = await client.GetAsync("/api/values"); - response.EnsureSuccessStatusCode(); + var test = await client.GetStringAsync("/api/values"); - var responseString = await response.Content.ReadAsStringAsync(); - var values = JsonConvert.DeserializeObject>(responseString); + var values = await client.GetFromJsonAsync>("/api/values"); Assert.Contains( new Link diff --git a/src/RiskFirst.Hateoas.Models/Link.cs b/src/RiskFirst.Hateoas.Models/Link.cs index 9bd8ee7..ec8f2b0 100644 --- a/src/RiskFirst.Hateoas.Models/Link.cs +++ b/src/RiskFirst.Hateoas.Models/Link.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; using System.Xml.Serialization; namespace RiskFirst.Hateoas.Models diff --git a/src/RiskFirst.Hateoas.Models/LinkCollection.cs b/src/RiskFirst.Hateoas.Models/LinkCollection.cs index 00214e3..42fef1c 100644 --- a/src/RiskFirst.Hateoas.Models/LinkCollection.cs +++ b/src/RiskFirst.Hateoas.Models/LinkCollection.cs @@ -1,6 +1,6 @@ -using Newtonsoft.Json; -using System.Collections; +using System.Collections; using System.Collections.Generic; +using System.Text.Json.Serialization; namespace RiskFirst.Hateoas.Models { diff --git a/src/RiskFirst.Hateoas.Models/LinkCollectionConverter.cs b/src/RiskFirst.Hateoas.Models/LinkCollectionConverter.cs index e95552f..5de06e2 100644 --- a/src/RiskFirst.Hateoas.Models/LinkCollectionConverter.cs +++ b/src/RiskFirst.Hateoas.Models/LinkCollectionConverter.cs @@ -1,16 +1,18 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; namespace RiskFirst.Hateoas.Models { public class LinkCollectionConverter : JsonConverter { - public override LinkCollection ReadJson(JsonReader reader, Type objectType, LinkCollection existingValue, bool hasExistingValue, JsonSerializer serializer) + public override LinkCollection Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var links = (Dictionary)serializer - .Deserialize(reader, typeof(Dictionary)); + var links = JsonSerializer.Deserialize>(ref reader, options); + + var existingValue = new LinkCollection(); foreach (var link in links) { @@ -21,12 +23,11 @@ public override LinkCollection ReadJson(JsonReader reader, Type objectType, Link return existingValue; } - public override void WriteJson(JsonWriter writer, LinkCollection value, JsonSerializer serializer) + public override void Write(Utf8JsonWriter writer, LinkCollection value, JsonSerializerOptions options) { - var links = value? - .ToDictionary(x => x.Name, x => x); + var links = value?.ToDictionary(x => x.Name, x => x); - serializer.Serialize(writer, links); + JsonSerializer.Serialize(writer, links); } } } diff --git a/src/RiskFirst.Hateoas.Models/LinkContainer.cs b/src/RiskFirst.Hateoas.Models/LinkContainer.cs index ca570e6..7300961 100644 --- a/src/RiskFirst.Hateoas.Models/LinkContainer.cs +++ b/src/RiskFirst.Hateoas.Models/LinkContainer.cs @@ -1,13 +1,12 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using System.Xml.Serialization; +using System.Xml.Serialization; +using System.Text.Json.Serialization; namespace RiskFirst.Hateoas.Models { public abstract class LinkContainer : ILinkContainer { [XmlElement("link")] - [JsonProperty(PropertyName = "_links")] + [JsonPropertyName("_links")] public LinkCollection Links { get; set; } = new LinkCollection(); public void Add(Link link) diff --git a/src/RiskFirst.Hateoas.Models/RiskFirst.Hateoas.Models.csproj b/src/RiskFirst.Hateoas.Models/RiskFirst.Hateoas.Models.csproj index 8365411..e7de5ba 100644 --- a/src/RiskFirst.Hateoas.Models/RiskFirst.Hateoas.Models.csproj +++ b/src/RiskFirst.Hateoas.Models/RiskFirst.Hateoas.Models.csproj @@ -21,15 +21,16 @@ v3.1.1 - version bump to match main assembly v3.1.2 - Patch Security Issues v4.0.0 - version bump to match main assembly + v5.0.0 - using System.Text.Json - 4.0.0 + 5.0.0 https://raw.githubusercontent.com/riskfirst/pkgicons/master/riskfirst-pkg.png - 4.0.0.0 - 4.0.0.0 + 5.0.0.0 + 5.0.0.0 - + diff --git a/tests/RiskFirst.Hateoas.Tests/JsonSerializationTests.cs b/tests/RiskFirst.Hateoas.Tests/JsonSerializationTests.cs index 1a7ba98..71577a7 100644 --- a/tests/RiskFirst.Hateoas.Tests/JsonSerializationTests.cs +++ b/tests/RiskFirst.Hateoas.Tests/JsonSerializationTests.cs @@ -1,7 +1,7 @@ -using Newtonsoft.Json; -using RiskFirst.Hateoas.Models; +using RiskFirst.Hateoas.Models; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using Xunit; namespace RiskFirst.Hateoas.Tests @@ -22,10 +22,10 @@ public void WhenLinksAreAvailable_ShouldSerializeThemProperly() var container = new TestLinkContainer(testLinks); // Act - var result = JsonConvert.SerializeObject(container); + var result = JsonSerializer.Serialize(container); // Assert - var deserialized = JsonConvert.DeserializeObject(result); + var deserialized = JsonSerializer.Deserialize(result); Assert.True(deserialized.Links.Count > 0); @@ -47,10 +47,10 @@ public void WhenNoLinksAreAvailable_NoLinksShouldBeSerialized() var container = new TestLinkContainer(testLinks); // Act - var result = JsonConvert.SerializeObject(container); + var result = JsonSerializer.Serialize(container); // Assert - var deserialized = JsonConvert.DeserializeObject(result); + var deserialized = JsonSerializer.Deserialize(result); Assert.Equal(0, deserialized.Links.Count); } From 63966c9ee085677b584f6eb3b6a9720d5e326d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrico=20M=C3=BCller?= Date: Wed, 23 Oct 2024 14:34:45 +0200 Subject: [PATCH 2/3] Newtonsoft.Json references --- .../RiskFirst.Hateoas.BasicSample.csproj | 6 +----- .../RiskFirst.Hateoas.BasicSample.Tests.csproj | 3 +-- .../RiskFirst.Hateoas.CustomRequirementSample.csproj | 6 +----- .../RiskFirst.Hateoas.CustomRequirementsSample.Tests.csproj | 3 +-- .../RiskFirst.Hateoas.LinkConfigurationSample/Program.cs | 3 +-- .../RiskFirst.Hateoas.LinkConfigurationSample.csproj | 6 +----- 6 files changed, 6 insertions(+), 21 deletions(-) diff --git a/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/RiskFirst.Hateoas.BasicSample.csproj b/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/RiskFirst.Hateoas.BasicSample.csproj index 7f31503..d295931 100644 --- a/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/RiskFirst.Hateoas.BasicSample.csproj +++ b/Samples/RiskFirst.Hateoas.BasicSample/src/RiskFirst.Hateoas.BasicSample/RiskFirst.Hateoas.BasicSample.csproj @@ -1,4 +1,4 @@ - + net7.0 enable @@ -8,8 +8,4 @@ - - - - diff --git a/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/RiskFirst.Hateoas.BasicSample.Tests.csproj b/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/RiskFirst.Hateoas.BasicSample.Tests.csproj index 99c1060..aa35b9d 100644 --- a/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/RiskFirst.Hateoas.BasicSample.Tests.csproj +++ b/Samples/RiskFirst.Hateoas.BasicSample/tests/RiskFirst.Hateoas.BasicSample.Tests/RiskFirst.Hateoas.BasicSample.Tests.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -10,7 +10,6 @@ - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/RiskFirst.Hateoas.CustomRequirementSample.csproj b/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/RiskFirst.Hateoas.CustomRequirementSample.csproj index b328e76..e4b6717 100644 --- a/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/RiskFirst.Hateoas.CustomRequirementSample.csproj +++ b/Samples/RiskFirst.Hateoas.CustomRequirementSample/src/RiskFirst.Hateoas.CustomRequirementSample/RiskFirst.Hateoas.CustomRequirementSample.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -9,8 +9,4 @@ - - - - diff --git a/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests.csproj b/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests.csproj index ecbda3c..2885387 100644 --- a/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests.csproj +++ b/Samples/RiskFirst.Hateoas.CustomRequirementSample/tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests/RiskFirst.Hateoas.CustomRequirementsSample.Tests.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -10,7 +10,6 @@ - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/Program.cs b/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/Program.cs index 96e060d..90c9b47 100644 --- a/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/Program.cs +++ b/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/Program.cs @@ -12,8 +12,7 @@ private static void Main(string[] args) var services = builder.Services; - services.AddControllers() - .AddNewtonsoftJson(); + services.AddControllers(); services.AddScoped(); services.AddLinks(config => { diff --git a/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/RiskFirst.Hateoas.LinkConfigurationSample.csproj b/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/RiskFirst.Hateoas.LinkConfigurationSample.csproj index b328e76..e4b6717 100644 --- a/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/RiskFirst.Hateoas.LinkConfigurationSample.csproj +++ b/Samples/RiskFirst.Hateoas.LinkConfigurationSample/src/RiskFirst.Hateoas.LinkConfigurationSample/RiskFirst.Hateoas.LinkConfigurationSample.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -9,8 +9,4 @@ - - - - From 63c4d26b5b1a9773b8f80fa03db1e8e1da61363a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrico=20M=C3=BCller?= Date: Wed, 23 Oct 2024 14:37:10 +0200 Subject: [PATCH 3/3] RiskFirst.Hateoas v5.0.0 --- src/RiskFirst.Hateoas/RiskFirst.Hateoas.csproj | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/RiskFirst.Hateoas/RiskFirst.Hateoas.csproj b/src/RiskFirst.Hateoas/RiskFirst.Hateoas.csproj index 35d92da..b6613f0 100644 --- a/src/RiskFirst.Hateoas/RiskFirst.Hateoas.csproj +++ b/src/RiskFirst.Hateoas/RiskFirst.Hateoas.csproj @@ -29,11 +29,12 @@ v3.1.1 - bug fix for routes with more than 1 HttpMethodAttribute v3.1.2 - Patch Security Issues v4.0.0 - Drop .NET Framework support + v5.0.0 - RiskFirst.Hateoas.Models v5.0.0 - 4.0.0 + 5.0.0 https://raw.githubusercontent.com/riskfirst/pkgicons/master/riskfirst-pkg.png - 4.0.0.0 - 4.0.0.0 + 5.0.0.0 + 5.0.0.0