From 10c18e4162699017ff722330ff350db36e776eea Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 29 Feb 2024 14:38:32 +0100 Subject: [PATCH] Swap Newtonsoft.Json dependency for System.Text.Json in BlockEditorPropertyNotificationHandlerBase (#15790) * Swap Newtonsoft.Json dependency for System.Text.Json in BlockEditorPropertyNotificationHandlerBase * Review comments --- ...ckEditorPropertyNotificationHandlerBase.cs | 47 +++++------ .../BlockEditorComponentTests.cs | 84 +++++++++---------- 2 files changed, 62 insertions(+), 69 deletions(-) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyNotificationHandlerBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyNotificationHandlerBase.cs index dccc6a7201..a2f5a3564e 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyNotificationHandlerBase.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyNotificationHandlerBase.cs @@ -1,6 +1,7 @@ -using System.Text.RegularExpressions; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; using Umbraco.Cms.Core.Models.Blocks; using Umbraco.Extensions; @@ -39,7 +40,7 @@ public abstract class BlockEditorPropertyNotificationHandlerBase(); obj = ParseObject(str); } @@ -102,30 +104,27 @@ public abstract class BlockEditorPropertyNotificationHandlerBase n.Value).WhereNotNull()) { TraverseProperty(property); } } - private void ParseUdis(JArray contentData, JArray settingsData) + private void ParseUdis(JsonArray contentData, JsonArray settingsData) { // grab all UDIs from the objects of contentData and settingsData - var udis = contentData.Select(c => c.SelectToken("$.udi")) - .Union(settingsData.Select(s => s.SelectToken("$.udi"))) - .Select(udiToken => udiToken?.Value()?.NullOrWhiteSpaceAsNull()) + var udis = contentData.Select(c => c?["udi"]) + .Union(settingsData.Select(s => s?["udi"])) + .Select(udiToken => udiToken?.GetValue().NullOrWhiteSpaceAsNull()) .ToArray(); // the following is solely for avoiding functionality wise breakage. we should consider removing it eventually, but for the time being it's harmless. @@ -139,16 +138,16 @@ public abstract class BlockEditorPropertyNotificationHandlerBase()) + foreach (JsonObject item in contentData.Union(settingsData).WhereNotNull().OfType()) { - foreach (JProperty property in item.Properties().Where(p => p.Name != "contentTypeKey" && p.Name != "udi")) + foreach (JsonNode property in item.Where(p => p.Key != "contentTypeKey" && p.Key != "udi").Select(p => p.Value).WhereNotNull()) { TraverseProperty(property); } } } - private JObject? ParseObject(string json) + private JsonObject? ParseObject(string json) { if (json.DetectIsJson() == false) { @@ -157,7 +156,7 @@ public abstract class BlockEditorPropertyNotificationHandlerBase>()); var result = component.ReplaceBlockEditorUdis(json, GuidFactory); + Assert.AreEqual(3, guidMap.Count); var expected = ReplaceGuids(json, guidMap); - var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(expected, _serializerSettings), _serializerSettings); - var resultJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result, _serializerSettings), _serializerSettings); - Console.WriteLine(expectedJson); - Console.WriteLine(resultJson); + var expectedJson = _jsonSerializer.Serialize( _jsonSerializer.Deserialize(expected)); + var resultJson = _jsonSerializer.Serialize(_jsonSerializer.Deserialize(result)); + Assert.IsNotEmpty(resultJson); Assert.AreEqual(expectedJson, resultJson); } @@ -74,7 +70,7 @@ public class BlockEditorComponentTests // we need to ensure the escaped json is consistent with how it will be re-escaped after parsing // and this is how to do that, the result will also include quotes around it. - var innerJsonEscaped = JsonConvert.ToString(innerJson); + var innerJsonEscaped = Escape(innerJson); // get the json with the subFeatures as escaped var json = GetBlockListJson(innerJsonEscaped); @@ -83,12 +79,12 @@ public class BlockEditorComponentTests var result = component.ReplaceBlockEditorUdis(json, GuidFactory); // the expected result is that the subFeatures data remains escaped + Assert.AreEqual(6, guidMap.Count); var expected = ReplaceGuids(GetBlockListJson(innerJsonEscaped), guidMap); - var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(expected, _serializerSettings), _serializerSettings); - var resultJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result, _serializerSettings), _serializerSettings); - Console.WriteLine(expectedJson); - Console.WriteLine(resultJson); + var expectedJson = _jsonSerializer.Serialize( _jsonSerializer.Deserialize(expected)); + var resultJson = _jsonSerializer.Serialize(_jsonSerializer.Deserialize(result)); + Assert.IsNotEmpty(resultJson); Assert.AreEqual(expectedJson, resultJson); } @@ -111,11 +107,11 @@ public class BlockEditorComponentTests var component = new BlockListPropertyNotificationHandler(Mock.Of>()); var result = component.ReplaceBlockEditorUdis(json, GuidFactory); + Assert.AreEqual(6, guidMap.Count); var expected = ReplaceGuids(GetBlockListJson(innerJson), guidMap); - var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(expected, _serializerSettings), _serializerSettings); - var resultJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result, _serializerSettings), _serializerSettings); - Console.WriteLine(expectedJson); - Console.WriteLine(resultJson); + var expectedJson = _jsonSerializer.Serialize( _jsonSerializer.Deserialize(expected)); + var resultJson = _jsonSerializer.Serialize(_jsonSerializer.Deserialize(result)); + Assert.IsNotEmpty(resultJson); Assert.AreEqual(expectedJson, resultJson); } @@ -133,7 +129,7 @@ public class BlockEditorComponentTests // we need to ensure the escaped json is consistent with how it will be re-escaped after parsing // and this is how to do that, the result will also include quotes around it. - var innerJsonEscaped = JsonConvert.ToString(innerJson); + var innerJsonEscaped = Escape(innerJson); // Complex editor such as the grid var complexEditorJsonEscaped = GetGridJson(innerJsonEscaped); @@ -144,13 +140,12 @@ public class BlockEditorComponentTests var result = component.ReplaceBlockEditorUdis(json, GuidFactory); // the expected result is that the subFeatures remains escaped - Assert.True(guidMap.Any()); + Assert.AreEqual(6, guidMap.Count); var expected = ReplaceGuids(GetBlockListJson(GetGridJson(innerJsonEscaped)), guidMap); - var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(expected, _serializerSettings), _serializerSettings); - var resultJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result, _serializerSettings), _serializerSettings); - Console.WriteLine(expectedJson); - Console.WriteLine(resultJson); + var expectedJson = _jsonSerializer.Serialize( _jsonSerializer.Deserialize(expected)); + var resultJson = _jsonSerializer.Serialize(_jsonSerializer.Deserialize(result)); + Assert.IsNotEmpty(resultJson); Assert.AreEqual(expectedJson, resultJson); } @@ -168,7 +163,7 @@ public class BlockEditorComponentTests // we need to ensure the escaped json is consistent with how it will be re-escaped after parsing // and this is how to do that, the result will also include quotes around it. - var innerJsonEscaped = JsonConvert.ToString(innerJson); + var innerJsonEscaped = Escape(innerJson); var json = GetBlockGridJson(innerJsonEscaped); @@ -176,13 +171,12 @@ public class BlockEditorComponentTests var result = component.ReplaceBlockEditorUdis(json, GuidFactory); // the expected result is that the subFeatures remains escaped - Assert.True(guidMap.Any()); + Assert.AreEqual(13, guidMap.Count); var expected = ReplaceGuids(GetBlockGridJson(innerJsonEscaped), guidMap); - var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(expected, _serializerSettings), _serializerSettings); - var resultJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result, _serializerSettings), _serializerSettings); - Console.WriteLine(expectedJson); - Console.WriteLine(resultJson); + var expectedJson = _jsonSerializer.Serialize( _jsonSerializer.Deserialize(expected)); + var resultJson = _jsonSerializer.Serialize(_jsonSerializer.Deserialize(result)); + Assert.IsNotEmpty(resultJson); Assert.AreEqual(expectedJson, resultJson); } @@ -204,13 +198,12 @@ public class BlockEditorComponentTests var result = component.ReplaceBlockEditorUdis(json, GuidFactory); // the expected result is that the subFeatures remains unescaped - Assert.True(guidMap.Any()); + Assert.AreEqual(13, guidMap.Count); var expected = ReplaceGuids(GetBlockGridJson(innerJson), guidMap); - var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(expected, _serializerSettings), _serializerSettings); - var resultJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result, _serializerSettings), _serializerSettings); - Console.WriteLine(expectedJson); - Console.WriteLine(resultJson); + var expectedJson = _jsonSerializer.Serialize( _jsonSerializer.Deserialize(expected)); + var resultJson = _jsonSerializer.Serialize(_jsonSerializer.Deserialize(result)); + Assert.IsNotEmpty(resultJson); Assert.AreEqual(expectedJson, resultJson); } @@ -238,13 +231,12 @@ public class BlockEditorComponentTests var result = component.ReplaceBlockEditorUdis(json, GuidFactory); // the expected result is that the subFeatures remains unaltered - the UDIs within should still exist - Assert.True(guidMap.Any()); + Assert.AreEqual(10, guidMap.Count); var expected = ReplaceGuids(GetBlockGridJson(innerJson), guidMap); - var expectedJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(expected, _serializerSettings), _serializerSettings); - var resultJson = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result, _serializerSettings), _serializerSettings); - Console.WriteLine(expectedJson); - Console.WriteLine(resultJson); + var expectedJson = _jsonSerializer.Serialize( _jsonSerializer.Deserialize(expected)); + var resultJson = _jsonSerializer.Serialize(_jsonSerializer.Deserialize(result)); + Assert.IsNotEmpty(resultJson); Assert.AreEqual(expectedJson, resultJson); Assert.True(result.Contains("umb://element/eb459ab17259495b90a3d2f6bb299826")); @@ -294,7 +286,7 @@ public class BlockEditorComponentTests ""udi"": ""umb://element/" + settingsGuid1 + @""", ""featureName"": ""Setting 1"", ""featureDetails"": ""Setting 2"" - }, + } ] }"; @@ -471,4 +463,6 @@ public class BlockEditorComponentTests return json; } + + private string Escape(string json) => $"\"{System.Web.HttpUtility.JavaScriptStringEncode(json)}\""; }