From 2dcdff539230c8db199776a50196c2594a3011e9 Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 14 Feb 2024 12:10:45 +0100 Subject: [PATCH] V14: Migrate nucache to use System.Text.Json (#15685) * Create system text serializer * Assign property names with system text * Use the new serializer * Impement AutoInterningStringConverter with System.Text.Json * Implement TextAutoInterningStringKeyCaseInsensitiveDictionaryConverter * Make CaseInsensitiveDictionaryConverter * Force datetimes to be read as UTC * Remove usages of Newtonsoft.Json * Remove text prefixes * Remove unused Newtonsoft converter * Remove more newtonsoft * Remove duplicate implementation * Rmove usage of missing class in tests * Ignore null values * Fix tests * Remove Newtonstoft reference from NuCache --------- Co-authored-by: Elitsa --- .../AutoInterningStringConverter.cs | 49 ++++------- ...ngKeyCaseInsensitiveDictionaryConverter.cs | 69 +++++++-------- .../CaseInsensitiveDictionaryConverter.cs | 38 ++++---- .../Serialization/ForceInt32Converter.cs | 21 ----- .../ForceUtcDateTimeConverter.cs | 20 +++++ .../DataSource/ContentCacheDataModel.cs | 17 ++-- .../DataSource/CultureVariation.cs | 21 +++-- .../JsonContentNestedDataSerializer.cs | 86 ++++--------------- .../DataSource/PropertyData.cs | 13 ++- .../Umbraco.PublishedCache.NuCache.csproj | 1 - .../ContentTypeServiceVariantsTests.cs | 66 +++++++------- .../ContentSerializationTests.cs | 1 - .../AutoInterningStringConverterTests.cs | 13 ++- 13 files changed, 167 insertions(+), 248 deletions(-) delete mode 100644 src/Umbraco.Infrastructure/Serialization/ForceInt32Converter.cs create mode 100644 src/Umbraco.Infrastructure/Serialization/ForceUtcDateTimeConverter.cs diff --git a/src/Umbraco.Infrastructure/Serialization/AutoInterningStringConverter.cs b/src/Umbraco.Infrastructure/Serialization/AutoInterningStringConverter.cs index 93c06d667e..8f174c2139 100644 --- a/src/Umbraco.Infrastructure/Serialization/AutoInterningStringConverter.cs +++ b/src/Umbraco.Infrastructure/Serialization/AutoInterningStringConverter.cs @@ -1,39 +1,26 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Umbraco.Cms.Infrastructure.Serialization; -/// -/// When applied to a string or string collection field will ensure the deserialized strings are interned -/// -/// -/// Borrowed from https://stackoverflow.com/a/34906004/694494 -/// On the same page an interesting approach of using a local intern pool https://stackoverflow.com/a/39605620/694494 -/// which re-uses .NET System.Xml.NameTable -/// -public class AutoInterningStringConverter : JsonConverter +public class AutoInterningStringConverter : JsonConverter { - public override bool CanWrite => false; + // This is a hacky workaround to creating a "read only converter", since System.Text.Json doesn't support it. + // Taken from https://github.com/dotnet/runtime/issues/46372#issuecomment-1660515178 + private readonly JsonConverter _fallbackConverter = (JsonConverter)JsonSerializerOptions.Default.GetConverter(typeof(string)); - public override bool CanConvert(Type objectType) => throw - - // CanConvert is not called when a converter is applied directly to a property. - new NotImplementedException($"{nameof(AutoInterningStringConverter)} should not be used globally"); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) + public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => + reader.TokenType switch { - return null; - } + JsonTokenType.Null => null, + JsonTokenType.String => + // It's safe to ignore nullability here, because according to the docs: + // Returns null when TokenType is JsonTokenType.Null + // https://learn.microsoft.com/en-us/dotnet/api/system.text.json.utf8jsonreader.getstring?view=net-8.0#remarks + string.Intern(reader.GetString()!), + _ => throw new InvalidOperationException($"{nameof(AutoInterningStringConverter)} only supports strings."), + }; - // Check is in case the value is a non-string literal such as an integer. - var s = reader.TokenType == JsonToken.String - ? string.Intern((string)reader.Value!) - : string.Intern((string)JToken.Load(reader)!); - return s; - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - throw new NotImplementedException(); + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) + => _fallbackConverter.Write(writer, value, options); } diff --git a/src/Umbraco.Infrastructure/Serialization/AutoInterningStringKeyCaseInsensitiveDictionaryConverter.cs b/src/Umbraco.Infrastructure/Serialization/AutoInterningStringKeyCaseInsensitiveDictionaryConverter.cs index df274f60ae..68c4e3f70b 100644 --- a/src/Umbraco.Infrastructure/Serialization/AutoInterningStringKeyCaseInsensitiveDictionaryConverter.cs +++ b/src/Umbraco.Infrastructure/Serialization/AutoInterningStringKeyCaseInsensitiveDictionaryConverter.cs @@ -1,54 +1,49 @@ -using System.Collections; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Umbraco.Cms.Infrastructure.Serialization; -/// -/// When applied to a dictionary with a string key, will ensure the deserialized string keys are interned -/// -/// -/// -/// borrowed from https://stackoverflow.com/a/36116462/694494 -/// -public class AutoInterningStringKeyCaseInsensitiveDictionaryConverter : CaseInsensitiveDictionaryConverter +public class AutoInterningStringKeyCaseInsensitiveDictionaryConverter : JsonConverter> { - public AutoInterningStringKeyCaseInsensitiveDictionaryConverter() - { - } + // This is a hacky workaround to creating a "read only converter", since System.Text.Json doesn't support it. + // Taken from https://github.com/dotnet/runtime/issues/46372#issuecomment-1660515178 + private readonly JsonConverter> _fallbackConverter = (JsonConverter>)JsonSerializerOptions.Default.GetConverter(typeof(IDictionary)); - public AutoInterningStringKeyCaseInsensitiveDictionaryConverter(StringComparer comparer) - : base(comparer) - { - } + /// + public override bool CanConvert(Type typeToConvert) => typeof(IDictionary).IsAssignableFrom(typeToConvert); - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) + public override Dictionary? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - if (reader.TokenType == JsonToken.StartObject) + if (reader.TokenType != JsonTokenType.StartObject) { - IDictionary dictionary = Create(objectType); - while (reader.Read()) + return null; + } + + var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); + while (reader.Read()) + { + switch (reader.TokenType) { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - var key = string.Intern(reader.Value!.ToString()!); + case JsonTokenType.PropertyName: + var key = string.Intern(reader.GetString()!); - if (!reader.Read()) - { - throw new Exception("Unexpected end when reading object."); - } + if (reader.Read() is false) + { + throw new JsonException(); + } - TValue? v = serializer.Deserialize(reader); - dictionary[key] = v; - break; - case JsonToken.Comment: - break; - case JsonToken.EndObject: - return dictionary; - } + TValue? value = JsonSerializer.Deserialize(ref reader, options); + dictionary[key] = value!; + break; + case JsonTokenType.Comment: + break; + case JsonTokenType.EndObject: + return dictionary; } } return null; } + + public override void Write(Utf8JsonWriter writer, IDictionary value, JsonSerializerOptions options) => _fallbackConverter.Write(writer, value, options); } diff --git a/src/Umbraco.Infrastructure/Serialization/CaseInsensitiveDictionaryConverter.cs b/src/Umbraco.Infrastructure/Serialization/CaseInsensitiveDictionaryConverter.cs index 08bbea155c..5dd7e5ea79 100644 --- a/src/Umbraco.Infrastructure/Serialization/CaseInsensitiveDictionaryConverter.cs +++ b/src/Umbraco.Infrastructure/Serialization/CaseInsensitiveDictionaryConverter.cs @@ -1,32 +1,24 @@ -using System.Collections; -using Newtonsoft.Json.Converters; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Umbraco.Cms.Infrastructure.Serialization; -/// -/// Marks dictionaries so they are deserialized as case-insensitive. -/// -/// -/// [JsonConverter(typeof(CaseInsensitiveDictionaryConverter{PropertyData[]}))] -/// public Dictionary{string, PropertyData[]} PropertyData {{ get; set; }} -/// -public class CaseInsensitiveDictionaryConverter : CustomCreationConverter +public class CaseInsensitiveDictionaryConverter : JsonConverter> { - private readonly StringComparer _comparer; + // This is a hacky workaround to creating a "read only converter", since System.Text.Json doesn't support it. + // Taken from https://github.com/dotnet/runtime/issues/46372#issuecomment-1660515178 + private readonly JsonConverter> _fallbackConverter = (JsonConverter>)JsonSerializerOptions.Default.GetConverter(typeof(IDictionary)); - public CaseInsensitiveDictionaryConverter() - : this(StringComparer.OrdinalIgnoreCase) + public override IDictionary? Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) { + IDictionary? defaultDictionary = JsonSerializer.Deserialize>(ref reader, options); + return defaultDictionary is null + ? null + : new Dictionary(defaultDictionary, StringComparer.OrdinalIgnoreCase); } - public CaseInsensitiveDictionaryConverter(StringComparer comparer) => - _comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); - - public override bool CanWrite => false; - - public override bool CanRead => true; - - public override bool CanConvert(Type objectType) => typeof(IDictionary).IsAssignableFrom(objectType); - - public override IDictionary Create(Type objectType) => new Dictionary(_comparer); + public override void Write(Utf8JsonWriter writer, IDictionary value, JsonSerializerOptions options) => _fallbackConverter.Write(writer, value, options); } diff --git a/src/Umbraco.Infrastructure/Serialization/ForceInt32Converter.cs b/src/Umbraco.Infrastructure/Serialization/ForceInt32Converter.cs deleted file mode 100644 index 49a00628e3..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/ForceInt32Converter.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -public class ForceInt32Converter : JsonConverter -{ - public override bool CanConvert(Type objectType) => objectType == typeof(object) || objectType == typeof(int); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - JValue? jsonValue = serializer.Deserialize(reader); - - return jsonValue?.Type == JTokenType.Integer - ? jsonValue.Value() - : serializer.Deserialize(reader); - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - throw new NotImplementedException(); -} diff --git a/src/Umbraco.Infrastructure/Serialization/ForceUtcDateTimeConverter.cs b/src/Umbraco.Infrastructure/Serialization/ForceUtcDateTimeConverter.cs new file mode 100644 index 0000000000..5b6aadbd07 --- /dev/null +++ b/src/Umbraco.Infrastructure/Serialization/ForceUtcDateTimeConverter.cs @@ -0,0 +1,20 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Umbraco.Cms.Infrastructure.Serialization; + +/// +/// In order to match the existing behaviour, and that os messagepack, we need to ensure that DateTimes are always read as UTC. +/// This is not the case by default for System.Text.Json, see: https://github.com/dotnet/runtime/issues/1566 +/// +public class ForceUtcDateTimeConverter : JsonConverter +{ + private readonly JsonConverter _fallBackConverter = (JsonConverter)JsonSerializerOptions.Default.GetConverter(typeof(DateTime)); + + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => reader.GetDateTime().ToUniversalTime(); + + // The existing behaviour is fine for writing, it's only reading that's an issue. + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + => _fallBackConverter.Write(writer, value, options); +} diff --git a/src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataModel.cs b/src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataModel.cs index d03aecbfa3..b85510b5c9 100644 --- a/src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataModel.cs +++ b/src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataModel.cs @@ -1,6 +1,6 @@ using System.Runtime.Serialization; +using System.Text.Json.Serialization; using MessagePack; -using Newtonsoft.Json; using Umbraco.Cms.Infrastructure.Serialization; namespace Umbraco.Cms.Infrastructure.PublishedCache.DataSource; @@ -14,34 +14,33 @@ public class ContentCacheDataModel // TODO: We don't want to allocate empty arrays // dont serialize empty properties [DataMember(Order = 0)] - [JsonProperty("pd")] + [JsonPropertyName("pd")] [JsonConverter(typeof(AutoInterningStringKeyCaseInsensitiveDictionaryConverter))] [MessagePackFormatter(typeof(MessagePackAutoInterningStringKeyCaseInsensitiveDictionaryFormatter))] public Dictionary? PropertyData { get; set; } [DataMember(Order = 1)] - [JsonProperty("cd")] + [JsonPropertyName("cd")] [JsonConverter(typeof(AutoInterningStringKeyCaseInsensitiveDictionaryConverter))] - [MessagePackFormatter( - typeof(MessagePackAutoInterningStringKeyCaseInsensitiveDictionaryFormatter))] + [MessagePackFormatter(typeof(MessagePackAutoInterningStringKeyCaseInsensitiveDictionaryFormatter))] public Dictionary? CultureData { get; set; } [DataMember(Order = 2)] - [JsonProperty("us")] + [JsonPropertyName("us")] public string? UrlSegment { get; set; } // Legacy properties used to deserialize existing nucache db entries [IgnoreDataMember] - [JsonProperty("properties")] + [JsonPropertyName("properties")] [JsonConverter(typeof(CaseInsensitiveDictionaryConverter))] private Dictionary LegacyPropertyData { set => PropertyData = value; } [IgnoreDataMember] - [JsonProperty("cultureData")] + [JsonPropertyName("cultureData")] [JsonConverter(typeof(CaseInsensitiveDictionaryConverter))] private Dictionary LegacyCultureData { set => CultureData = value; } [IgnoreDataMember] - [JsonProperty("urlSegment")] + [JsonPropertyName("urlSegment")] private string LegacyUrlSegment { set => UrlSegment = value; } } diff --git a/src/Umbraco.PublishedCache.NuCache/DataSource/CultureVariation.cs b/src/Umbraco.PublishedCache.NuCache/DataSource/CultureVariation.cs index 8e3974cb43..8819aa5605 100644 --- a/src/Umbraco.PublishedCache.NuCache/DataSource/CultureVariation.cs +++ b/src/Umbraco.PublishedCache.NuCache/DataSource/CultureVariation.cs @@ -1,5 +1,6 @@ using System.Runtime.Serialization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Umbraco.Cms.Infrastructure.Serialization; namespace Umbraco.Cms.Infrastructure.PublishedCache.DataSource; @@ -10,35 +11,37 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache.DataSource; public class CultureVariation { [DataMember(Order = 0)] - [JsonProperty("nm")] + [JsonPropertyName("nm")] public string? Name { get; set; } [DataMember(Order = 1)] - [JsonProperty("us")] + [JsonPropertyName("us")] public string? UrlSegment { get; set; } [DataMember(Order = 2)] - [JsonProperty("dt")] + [JsonPropertyName("dt")] + [JsonConverter(typeof(ForceUtcDateTimeConverter))] public DateTime Date { get; set; } [DataMember(Order = 3)] - [JsonProperty("isd")] + [JsonPropertyName("isd")] public bool IsDraft { get; set; } // Legacy properties used to deserialize existing nucache db entries [IgnoreDataMember] - [JsonProperty("name")] + [JsonPropertyName("nam")] private string LegacyName { set => Name = value; } [IgnoreDataMember] - [JsonProperty("urlSegment")] + [JsonPropertyName("urlSegment")] private string LegacyUrlSegment { set => UrlSegment = value; } [IgnoreDataMember] - [JsonProperty("date")] + [JsonPropertyName("date")] + [JsonConverter(typeof(ForceUtcDateTimeConverter))] private DateTime LegacyDate { set => Date = value; } [IgnoreDataMember] - [JsonProperty("isDraft")] + [JsonPropertyName("isDraft")] private bool LegacyIsDraft { set => IsDraft = value; } } diff --git a/src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializer.cs b/src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializer.cs index 3ac2bfdf98..f0ab08c32a 100644 --- a/src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializer.cs +++ b/src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializer.cs @@ -1,28 +1,22 @@ -using System.Buffers; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Infrastructure.Serialization; namespace Umbraco.Cms.Infrastructure.PublishedCache.DataSource; public class JsonContentNestedDataSerializer : IContentCacheDataSerializer { - // by default JsonConvert will deserialize our numeric values as Int64 - // which is bad, because they were Int32 in the database - take care - private readonly JsonSerializerSettings _jsonSerializerSettings = new() + private static readonly JsonSerializerOptions _jsonSerializerOptions = new() { - Converters = new List { new ForceInt32Converter() }, - - // Explicitly specify date handling so that it's consistent and follows the same date handling as MessagePack - DateParseHandling = DateParseHandling.DateTime, - DateFormatHandling = DateFormatHandling.IsoDateFormat, - DateTimeZoneHandling = DateTimeZoneHandling.Utc, - DateFormatString = "o", + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; - private readonly JsonNameTable _propertyNameTable = new DefaultJsonNameTable(); - - public ContentCacheDataModel? Deserialize(IReadOnlyContentBase content, string? stringData, byte[]? byteData, bool published) + /// + public ContentCacheDataModel? Deserialize( + IReadOnlyContentBase content, + string? stringData, + byte[]? byteData, + bool published) { if (stringData == null && byteData != null) { @@ -30,62 +24,16 @@ public class JsonContentNestedDataSerializer : IContentCacheDataSerializer $"{typeof(JsonContentNestedDataSerializer)} does not support byte[] serialization"); } - var serializer = JsonSerializer.Create(_jsonSerializerSettings); - using (var reader = new JsonTextReader(new StringReader(stringData!))) - { - // reader will get buffer from array pool - reader.ArrayPool = JsonArrayPool.Instance; - reader.PropertyNameTable = _propertyNameTable; - return serializer.Deserialize(reader); - } + return JsonSerializer.Deserialize(stringData!, _jsonSerializerOptions); } - public ContentCacheDataSerializationResult Serialize(IReadOnlyContentBase content, ContentCacheDataModel model, bool published) + /// + public ContentCacheDataSerializationResult Serialize( + IReadOnlyContentBase content, + ContentCacheDataModel model, + bool published) { - // note that numeric values (which are Int32) are serialized without their - // type (eg "value":1234) and JsonConvert by default deserializes them as Int64 - var json = JsonConvert.SerializeObject(model); + var json = JsonSerializer.Serialize(model, _jsonSerializerOptions); return new ContentCacheDataSerializationResult(json, null); } } - -public class JsonArrayPool : IArrayPool -{ - public static readonly JsonArrayPool Instance = new(); - - public char[] Rent(int minimumLength) => - - // get char array from System.Buffers shared pool - ArrayPool.Shared.Rent(minimumLength); - - public void Return(char[]? array) - { - // return char array to System.Buffers shared pool - if (array is not null) - { - ArrayPool.Shared.Return(array); - } - } -} - -public class AutomaticJsonNameTable : DefaultJsonNameTable -{ - private readonly int maxToAutoAdd; - private int nAutoAdded; - - public AutomaticJsonNameTable(int maxToAdd) => maxToAutoAdd = maxToAdd; - - public override string? Get(char[] key, int start, int length) - { - var s = base.Get(key, start, length); - - if (s == null && nAutoAdded < maxToAutoAdd) - { - s = new string(key, start, length); - Add(s); - nAutoAdded++; - } - - return s; - } -} diff --git a/src/Umbraco.PublishedCache.NuCache/DataSource/PropertyData.cs b/src/Umbraco.PublishedCache.NuCache/DataSource/PropertyData.cs index 62da6727ac..4de0476c78 100644 --- a/src/Umbraco.PublishedCache.NuCache/DataSource/PropertyData.cs +++ b/src/Umbraco.PublishedCache.NuCache/DataSource/PropertyData.cs @@ -1,6 +1,6 @@ using System.ComponentModel; using System.Runtime.Serialization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using Umbraco.Cms.Infrastructure.Serialization; namespace Umbraco.Cms.Infrastructure.PublishedCache.DataSource; @@ -14,7 +14,7 @@ public class PropertyData [DataMember(Order = 0)] [JsonConverter(typeof(AutoInterningStringConverter))] [DefaultValue("")] - [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, PropertyName = "c")] + [JsonPropertyName("c")] public string? Culture { get => _culture; @@ -26,7 +26,7 @@ public class PropertyData [DataMember(Order = 1)] [JsonConverter(typeof(AutoInterningStringConverter))] [DefaultValue("")] - [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, PropertyName = "s")] + [JsonPropertyName("s")] public string? Segment { get => _segment; @@ -36,26 +36,25 @@ public class PropertyData } [DataMember(Order = 2)] - [JsonProperty("v")] + [JsonPropertyName("v")] public object? Value { get; set; } // Legacy properties used to deserialize existing nucache db entries [IgnoreDataMember] - [JsonProperty("culture")] private string LegacyCulture { set => Culture = value; } [IgnoreDataMember] - [JsonProperty("seg")] + [JsonPropertyName("seg")] private string LegacySegment { set => Segment = value; } [IgnoreDataMember] - [JsonProperty("val")] + [JsonPropertyName("val")] private object LegacyValue { set => Value = value; diff --git a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj index 75dfa13ec6..c37aa27bb4 100644 --- a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj +++ b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj @@ -10,7 +10,6 @@ - diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs index a21d9686ba..e4381ff3d9 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs @@ -568,7 +568,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'c':'en','v':'v1en'},{'c':'fr','v':'v1fr'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'en','s':'','v':'v1en'},{'c':'fr','s':'','v':'v1fr'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch content type to Nothing contentType.Variations = ContentVariation.Nothing; @@ -586,7 +586,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'v':'v1en'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'','s':'','v':'v1en'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch content back to Culture contentType.Variations = ContentVariation.Culture; @@ -604,7 +604,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'v':'v1en'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'','s':'','v':'v1en'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch property back to Culture contentType.PropertyTypes.First(x => x.Alias == "value1").Variations = ContentVariation.Culture; @@ -621,7 +621,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'c':'en','v':'v1en'},{'c':'fr','v':'v1fr'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'en','s':'','v':'v1en'},{'c':'fr','s':'','v':'v1fr'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); } [Test] @@ -664,7 +664,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'v':'v1'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'','s':'','v':'v1'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch content type to Culture contentType.Variations = ContentVariation.Culture; @@ -681,7 +681,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'v':'v1'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'','s':'','v':'v1'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch property to Culture contentType.PropertyTypes.First(x => x.Alias == "value1").Variations = ContentVariation.Culture; @@ -697,7 +697,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'c':'en','v':'v1'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'en','s':'','v':'v1'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch content back to Nothing contentType.Variations = ContentVariation.Nothing; @@ -715,7 +715,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'v':'v1'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'','s':'','v':'v1'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); } [Test] @@ -753,7 +753,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'c':'en','v':'v1en'},{'c':'fr','v':'v1fr'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'en','s':'','v':'v1en'},{'c':'fr','s':'','v':'v1fr'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch property type to Nothing contentType.PropertyTypes.First(x => x.Alias == "value1").Variations = ContentVariation.Nothing; @@ -771,7 +771,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'v':'v1en'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'','s':'','v':'v1en'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch property back to Culture contentType.PropertyTypes.First(x => x.Alias == "value1").Variations = ContentVariation.Culture; @@ -788,7 +788,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'c':'en','v':'v1en'},{'c':'fr','v':'v1fr'}],'value2':[{'v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'en','s':'','v':'v1en'},{'c':'fr','s':'','v':'v1fr'}],'value2':[{'c':'','s':'','v':'v2'}]},'cd':"); // switch other property to Culture contentType.PropertyTypes.First(x => x.Alias == "value2").Variations = ContentVariation.Culture; @@ -807,7 +807,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value1':[{'c':'en','v':'v1en'},{'c':'fr','v':'v1fr'}],'value2':[{'c':'en','v':'v2'}]},'cd':"); + "{'pd':{'value1':[{'c':'en','s':'','v':'v1en'},{'c':'fr','s':'','v':'v1fr'}],'value2':[{'c':'en','s':'','v':'v2'}]},'cd':"); } [TestCase(ContentVariation.Culture, ContentVariation.Nothing)] @@ -1070,7 +1070,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); composed.Variations = ContentVariation.Nothing; ContentTypeService.Save(composed); @@ -1079,7 +1079,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value11':[{'v':'v11en'}],'value12':[{'v':'v12'}],'value21':[{'v':'v21en'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11en'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'','s':'','v':'v21en'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); composed.Variations = ContentVariation.Culture; ContentTypeService.Save(composed); @@ -1088,7 +1088,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'v':'v21en'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'','s':'','v':'v21en'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); composed.PropertyTypes.First(x => x.Alias == "value21").Variations = ContentVariation.Culture; ContentTypeService.Save(composed); @@ -1097,7 +1097,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); composing.Variations = ContentVariation.Nothing; ContentTypeService.Save(composing); @@ -1106,7 +1106,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value11':[{'v':'v11en'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11en'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); composing.Variations = ContentVariation.Culture; ContentTypeService.Save(composing); @@ -1115,7 +1115,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value11':[{'v':'v11en'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11en'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); composing.PropertyTypes.First(x => x.Alias == "value11").Variations = ContentVariation.Culture; ContentTypeService.Save(composing); @@ -1124,7 +1124,7 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document.Id)); AssertJsonStartsWith( document.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); } [Test] @@ -1189,12 +1189,12 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document1.Id)); AssertJsonStartsWith( document1.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); Console.WriteLine(GetJson(document2.Id)); AssertJsonStartsWith( document2.Id, - "{'pd':{'value11':[{'v':'v11'}],'value12':[{'v':'v12'}],'value31':[{'v':'v31'}],'value32':[{'v':'v32'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11'}],'value12':[{'c':'','s':'','v':'v12'}],'value31':[{'c':'','s':'','v':'v31'}],'value32':[{'c':'','s':'','v':'v32'}]},'cd':"); composed1.Variations = ContentVariation.Nothing; ContentTypeService.Save(composed1); @@ -1203,12 +1203,12 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document1.Id)); AssertJsonStartsWith( document1.Id, - "{'pd':{'value11':[{'v':'v11en'}],'value12':[{'v':'v12'}],'value21':[{'v':'v21en'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11en'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'','s':'','v':'v21en'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); Console.WriteLine(GetJson(document2.Id)); AssertJsonStartsWith( document2.Id, - "{'pd':{'value11':[{'v':'v11'}],'value12':[{'v':'v12'}],'value31':[{'v':'v31'}],'value32':[{'v':'v32'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11'}],'value12':[{'c':'','s':'','v':'v12'}],'value31':[{'c':'','s':'','v':'v31'}],'value32':[{'c':'','s':'','v':'v32'}]},'cd':"); composed1.Variations = ContentVariation.Culture; ContentTypeService.Save(composed1); @@ -1217,12 +1217,12 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document1.Id)); AssertJsonStartsWith( document1.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'v':'v21en'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'','s':'','v':'v21en'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); Console.WriteLine(GetJson(document2.Id)); AssertJsonStartsWith( document2.Id, - "{'pd':{'value11':[{'v':'v11'}],'value12':[{'v':'v12'}],'value31':[{'v':'v31'}],'value32':[{'v':'v32'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11'}],'value12':[{'c':'','s':'','v':'v12'}],'value31':[{'c':'','s':'','v':'v31'}],'value32':[{'c':'','s':'','v':'v32'}]},'cd':"); composed1.PropertyTypes.First(x => x.Alias == "value21").Variations = ContentVariation.Culture; ContentTypeService.Save(composed1); @@ -1231,12 +1231,12 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document1.Id)); AssertJsonStartsWith( document1.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); Console.WriteLine(GetJson(document2.Id)); AssertJsonStartsWith( document2.Id, - "{'pd':{'value11':[{'v':'v11'}],'value12':[{'v':'v12'}],'value31':[{'v':'v31'}],'value32':[{'v':'v32'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11'}],'value12':[{'c':'','s':'','v':'v12'}],'value31':[{'c':'','s':'','v':'v31'}],'value32':[{'c':'','s':'','v':'v32'}]},'cd':"); composing.Variations = ContentVariation.Nothing; ContentTypeService.Save(composing); @@ -1245,12 +1245,12 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document1.Id)); AssertJsonStartsWith( document1.Id, - "{'pd':{'value11':[{'v':'v11en'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11en'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); Console.WriteLine(GetJson(document2.Id)); AssertJsonStartsWith( document2.Id, - "{'pd':{'value11':[{'v':'v11'}],'value12':[{'v':'v12'}],'value31':[{'v':'v31'}],'value32':[{'v':'v32'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11'}],'value12':[{'c':'','s':'','v':'v12'}],'value31':[{'c':'','s':'','v':'v31'}],'value32':[{'c':'','s':'','v':'v32'}]},'cd':"); composing.Variations = ContentVariation.Culture; ContentTypeService.Save(composing); @@ -1259,12 +1259,12 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document1.Id)); AssertJsonStartsWith( document1.Id, - "{'pd':{'value11':[{'v':'v11en'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11en'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); Console.WriteLine(GetJson(document2.Id)); AssertJsonStartsWith( document2.Id, - "{'pd':{'value11':[{'v':'v11'}],'value12':[{'v':'v12'}],'value31':[{'v':'v31'}],'value32':[{'v':'v32'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11'}],'value12':[{'c':'','s':'','v':'v12'}],'value31':[{'c':'','s':'','v':'v31'}],'value32':[{'c':'','s':'','v':'v32'}]},'cd':"); composing.PropertyTypes.First(x => x.Alias == "value11").Variations = ContentVariation.Culture; ContentTypeService.Save(composing); @@ -1273,12 +1273,12 @@ public class ContentTypeServiceVariantsTests : UmbracoIntegrationTest Console.WriteLine(GetJson(document1.Id)); AssertJsonStartsWith( document1.Id, - "{'pd':{'value11':[{'c':'en','v':'v11en'},{'c':'fr','v':'v11fr'}],'value12':[{'v':'v12'}],'value21':[{'c':'en','v':'v21en'},{'c':'fr','v':'v21fr'}],'value22':[{'v':'v22'}]},'cd':"); + "{'pd':{'value11':[{'c':'en','s':'','v':'v11en'},{'c':'fr','s':'','v':'v11fr'}],'value12':[{'c':'','s':'','v':'v12'}],'value21':[{'c':'en','s':'','v':'v21en'},{'c':'fr','s':'','v':'v21fr'}],'value22':[{'c':'','s':'','v':'v22'}]},'cd':"); Console.WriteLine(GetJson(document2.Id)); AssertJsonStartsWith( document2.Id, - "{'pd':{'value11':[{'v':'v11'}],'value12':[{'v':'v12'}],'value31':[{'v':'v31'}],'value32':[{'v':'v32'}]},'cd':"); + "{'pd':{'value11':[{'c':'','s':'','v':'v11'}],'value12':[{'c':'','s':'','v':'v12'}],'value31':[{'c':'','s':'','v':'v31'}],'value32':[{'c':'','s':'','v':'v32'}]},'cd':"); } private async Task CreateFrenchAndEnglishLangs() diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/PublishedCache/ContentSerializationTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/PublishedCache/ContentSerializationTests.cs index 9b45e85b7e..a6bc6439b7 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/PublishedCache/ContentSerializationTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/PublishedCache/ContentSerializationTests.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using Moq; using NUnit.Framework; using Umbraco.Cms.Core.Models; diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Serialization/AutoInterningStringConverterTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Serialization/AutoInterningStringConverterTests.cs index 442628d619..ccfed38b7e 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Serialization/AutoInterningStringConverterTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Serialization/AutoInterningStringConverterTests.cs @@ -1,6 +1,5 @@ -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; using NUnit.Framework; using Umbraco.Cms.Infrastructure.Serialization; @@ -18,8 +17,8 @@ public class AutoInterningStringConverterTests // ensure the raw value is not interned Assert.IsNull(string.IsInterned(obj.Name)); - var serialized = JsonConvert.SerializeObject(obj); - obj = JsonConvert.DeserializeObject(serialized); + var serialized = JsonSerializer.Serialize(obj); + obj = JsonSerializer.Deserialize(serialized); Assert.IsNotNull(string.IsInterned(obj.Name)); } @@ -37,8 +36,8 @@ public class AutoInterningStringConverterTests Assert.IsNull(string.IsInterned(obj.Values.Keys.First())); Assert.IsNull(string.IsInterned(obj.Values.Keys.Last())); - var serialized = JsonConvert.SerializeObject(obj); - obj = JsonConvert.DeserializeObject(serialized); + var serialized = JsonSerializer.Serialize(obj); + obj = JsonSerializer.Deserialize(serialized); Assert.IsNotNull(string.IsInterned(obj.Values.Keys.First())); Assert.IsNotNull(string.IsInterned(obj.Values.Keys.Last()));