From 403e5e5de0dd2c0b00fd08a054a48fb2b8ac65e6 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Sun, 14 Jul 2024 20:35:17 +0200 Subject: [PATCH] Get rid of Newtonsoft --- .../AutoDiscoveryProviderSetting.cs | 12 +-- .../AutoDiscovery/AutoDiscoverySettings.cs | 8 +- Wino.Core.Domain/Wino.Core.Domain.NET8.csproj | 1 - Wino.Core.Domain/Wino.Core.Domain.csproj | 2 +- .../Authenticators/GmailAuthenticator.cs | 29 +++--- .../Http/MicrosoftJsonContractResolver.cs | 36 -------- Wino.Core/Requests/Bundles/RequestBundle.cs | 4 +- Wino.Core/Services/AutoDiscoveryService.cs | 4 +- Wino.Core/Services/TranslationService.cs | 4 +- Wino.Core/Wino.Core.NET8.csproj | 1 - Wino.Core/Wino.Core.csproj | 1 - Wino.Mail.WinUI/Wino.Mail.WinUI.csproj | 1 - .../Dialogs/SignatureEditorDialog.xaml.cs | 10 +-- Wino.Mail/Helpers/JsonHelpers.cs | 25 ------ .../Helpers/SettingsStorageExtensions.cs | 88 ------------------- Wino.Mail/Views/ComposePage.xaml.cs | 11 +-- Wino.Mail/Views/MailRenderingPage.xaml.cs | 4 +- Wino.Mail/Wino.Mail.csproj | 1 - 18 files changed, 43 insertions(+), 199 deletions(-) delete mode 100644 Wino.Core/Http/MicrosoftJsonContractResolver.cs delete mode 100644 Wino.Mail/Helpers/JsonHelpers.cs diff --git a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs index dca80eb0..59abe9ae 100644 --- a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs +++ b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs @@ -1,22 +1,22 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Wino.Core.Domain.Models.AutoDiscovery { public class AutoDiscoveryProviderSetting { - [JsonProperty("protocol")] + [JsonPropertyName("protocol")] public string Protocol { get; set; } - [JsonProperty("address")] + [JsonPropertyName("address")] public string Address { get; set; } - [JsonProperty("port")] + [JsonPropertyName("port")] public int Port { get; set; } - [JsonProperty("secure")] + [JsonPropertyName("secure")] public string Secure { get; set; } - [JsonProperty("username")] + [JsonPropertyName("username")] public string Username { get; set; } } } diff --git a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs index dbc300e7..cfcb55ff 100644 --- a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs +++ b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs @@ -1,19 +1,19 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using Wino.Core.Domain.Entities; namespace Wino.Core.Domain.Models.AutoDiscovery { public class AutoDiscoverySettings { - [JsonProperty("domain")] + [JsonPropertyName("domain")] public string Domain { get; set; } - [JsonProperty("password")] + [JsonPropertyName("password")] public string Password { get; set; } - [JsonProperty("settings")] + [JsonPropertyName("settings")] public List Settings { get; set; } /// diff --git a/Wino.Core.Domain/Wino.Core.Domain.NET8.csproj b/Wino.Core.Domain/Wino.Core.Domain.NET8.csproj index 38a6d563..33b44636 100644 --- a/Wino.Core.Domain/Wino.Core.Domain.NET8.csproj +++ b/Wino.Core.Domain/Wino.Core.Domain.NET8.csproj @@ -55,7 +55,6 @@ - diff --git a/Wino.Core.Domain/Wino.Core.Domain.csproj b/Wino.Core.Domain/Wino.Core.Domain.csproj index 187841b8..c0159aae 100644 --- a/Wino.Core.Domain/Wino.Core.Domain.csproj +++ b/Wino.Core.Domain/Wino.Core.Domain.csproj @@ -50,8 +50,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Wino.Core/Authenticators/GmailAuthenticator.cs b/Wino.Core/Authenticators/GmailAuthenticator.cs index 2e623871..21ded84b 100644 --- a/Wino.Core/Authenticators/GmailAuthenticator.cs +++ b/Wino.Core/Authenticators/GmailAuthenticator.cs @@ -1,9 +1,9 @@ using System; using System.Net.Http; using System.Text; +using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Nito.AsyncEx; using Wino.Core.Domain; using Wino.Core.Domain.Entities; @@ -63,14 +63,14 @@ namespace Wino.Core.Authenticators if (!response.IsSuccessStatusCode) throw new GoogleAuthenticationException(Translator.Exception_GoogleAuthorizationCodeExchangeFailed); - var parsed = JObject.Parse(responseString); + var parsed = JsonNode.Parse(responseString).AsObject(); if (parsed.ContainsKey("error")) - throw new GoogleAuthenticationException(parsed["error"]["message"].Value()); + throw new GoogleAuthenticationException(parsed["error"]["message"].GetValue()); - var accessToken = parsed["access_token"].Value(); - var refreshToken = parsed["refresh_token"].Value(); - var expiresIn = parsed["expires_in"].Value(); + var accessToken = parsed["access_token"].GetValue(); + var refreshToken = parsed["refresh_token"].GetValue(); + var expiresIn = parsed["expires_in"].GetValue(); var expirationDate = DateTime.UtcNow.AddSeconds(expiresIn); @@ -81,12 +81,12 @@ namespace Wino.Core.Authenticators var userinfoResponse = await client.GetAsync(UserInfoEndpoint); string userinfoResponseContent = await userinfoResponse.Content.ReadAsStringAsync(); - var parsedUserInfo = JObject.Parse(userinfoResponseContent); + var parsedUserInfo = JsonNode.Parse(userinfoResponseContent).AsObject(); if (parsedUserInfo.ContainsKey("error")) - throw new GoogleAuthenticationException(parsedUserInfo["error"]["message"].Value()); + throw new GoogleAuthenticationException(parsedUserInfo["error"]["message"].GetValue()); - var username = parsedUserInfo["emailAddress"].Value(); + var username = parsedUserInfo["emailAddress"].GetValue(); return new TokenInformation() { @@ -182,14 +182,13 @@ namespace Wino.Core.Authenticators var response = await client.PostAsync(RefreshTokenEndpoint, content); string responseString = await response.Content.ReadAsStringAsync(); - - var parsed = JObject.Parse(responseString); + var parsed = JsonNode.Parse(responseString).AsObject(); // TODO: Error parsing is incorrect. if (parsed.ContainsKey("error")) - throw new GoogleAuthenticationException(parsed["error_description"].Value()); + throw new GoogleAuthenticationException(parsed["error_description"].GetValue()); - var accessToken = parsed["access_token"].Value(); + var accessToken = parsed["access_token"].GetValue(); string activeRefreshToken = refresh_token; @@ -199,10 +198,10 @@ namespace Wino.Core.Authenticators if (parsed.ContainsKey("refresh_token")) { - activeRefreshToken = parsed["refresh_token"].Value(); + activeRefreshToken = parsed["refresh_token"].GetValue(); } - var expiresIn = parsed["expires_in"].Value(); + var expiresIn = parsed["expires_in"].GetValue(); var expirationDate = DateTime.UtcNow.AddSeconds(expiresIn); return new TokenInformationBase() diff --git a/Wino.Core/Http/MicrosoftJsonContractResolver.cs b/Wino.Core/Http/MicrosoftJsonContractResolver.cs deleted file mode 100644 index 79148cbe..00000000 --- a/Wino.Core/Http/MicrosoftJsonContractResolver.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace Wino.Core.Http -{ - - /// - /// We need to generate HttpRequestMessage for batch requests, and sometimes we need to - /// serialize content as json. However, some of the fields like 'ODataType' must be ignored - /// in order PATCH requests to succeed. Therefore Microsoft account synchronizer uses - /// special JsonSerializerSettings for ignoring some of the properties. - /// - public class MicrosoftJsonContractResolver : DefaultContractResolver - { - private readonly HashSet ignoreProps = new HashSet() - { - "ODataType" - }; - - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - JsonProperty property = base.CreateProperty(member, memberSerialization); - - if (ignoreProps.Contains(property.PropertyName)) - { - property.ShouldSerialize = _ => false; - } - - return property; - } - } -} diff --git a/Wino.Core/Requests/Bundles/RequestBundle.cs b/Wino.Core/Requests/Bundles/RequestBundle.cs index bf8a7045..dd320d6b 100644 --- a/Wino.Core/Requests/Bundles/RequestBundle.cs +++ b/Wino.Core/Requests/Bundles/RequestBundle.cs @@ -1,9 +1,9 @@ using System; using System.Linq; using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json; using Wino.Core.Domain.Interfaces; namespace Wino.Core.Domain.Models.Requests @@ -43,7 +43,7 @@ namespace Wino.Core.Domain.Models.Requests { var content = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - return JsonConvert.DeserializeObject(content) ?? throw new InvalidOperationException("Invalid Http Response Deserialization"); + return JsonSerializer.Deserialize(content) ?? throw new InvalidOperationException("Invalid Http Response Deserialization"); } public override string ToString() diff --git a/Wino.Core/Services/AutoDiscoveryService.cs b/Wino.Core/Services/AutoDiscoveryService.cs index c788b130..dc4ee10f 100644 --- a/Wino.Core/Services/AutoDiscoveryService.cs +++ b/Wino.Core/Services/AutoDiscoveryService.cs @@ -1,7 +1,7 @@ using System; using System.Net.Http; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; using Serilog; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.AutoDiscovery; @@ -43,7 +43,7 @@ namespace Wino.Core.Services { var content = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(content); + return JsonSerializer.Deserialize(content); } catch (Exception ex) { diff --git a/Wino.Core/Services/TranslationService.cs b/Wino.Core/Services/TranslationService.cs index aea449fc..9cc1af10 100644 --- a/Wino.Core/Services/TranslationService.cs +++ b/Wino.Core/Services/TranslationService.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.IO; +using System.Text.Json; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; -using Newtonsoft.Json; using Serilog; using Wino.Core.Domain; using Wino.Core.Domain.Enums; @@ -44,7 +44,7 @@ namespace Wino.Core.Services var stremValue = await new StreamReader(resourceStream).ReadToEndAsync().ConfigureAwait(false); - var translationLookups = JsonConvert.DeserializeObject>(stremValue); + var translationLookups = JsonSerializer.Deserialize>(stremValue); // Insert new translation key-value pairs. // Overwrite existing values for the same keys. diff --git a/Wino.Core/Wino.Core.NET8.csproj b/Wino.Core/Wino.Core.NET8.csproj index 922683a7..5f9dd96f 100644 --- a/Wino.Core/Wino.Core.NET8.csproj +++ b/Wino.Core/Wino.Core.NET8.csproj @@ -19,7 +19,6 @@ - diff --git a/Wino.Core/Wino.Core.csproj b/Wino.Core/Wino.Core.csproj index f733ab26..308a0714 100644 --- a/Wino.Core/Wino.Core.csproj +++ b/Wino.Core/Wino.Core.csproj @@ -24,7 +24,6 @@ - diff --git a/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj b/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj index 16b451d5..339dcdcf 100644 --- a/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj +++ b/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj @@ -81,7 +81,6 @@ - diff --git a/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs index d4108506..48b9d0ae 100644 --- a/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs +++ b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs @@ -1,18 +1,16 @@ using System; using System.Text.RegularExpressions; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Web.WebView2.Core; -using Newtonsoft.Json; using Windows.UI.ViewManagement.Core; - using Wino.Core.Domain; using Wino.Core.Domain.Entities; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.Requests; using Wino.Views.Settings; - #if NET8_0 using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -82,7 +80,7 @@ namespace Wino.Dialogs { var editorContent = await InvokeScriptSafeAsync("GetHTMLContent();"); - return JsonConvert.DeserializeObject(editorContent); + return JsonSerializer.Deserialize(editorContent); }); var underlyingThemeService = App.Current.Services.GetService(); @@ -197,7 +195,7 @@ namespace Wino.Dialogs string script = functionName + "("; for (int i = 0; i < parameters.Length; i++) { - script += JsonConvert.SerializeObject(parameters[i]); + script += JsonSerializer.Serialize(parameters[i]); if (i < parameters.Length - 1) { script += ", "; @@ -320,7 +318,7 @@ namespace Wino.Dialogs private void ScriptMessageReceived(CoreWebView2 sender, CoreWebView2WebMessageReceivedEventArgs args) { - var change = JsonConvert.DeserializeObject(args.WebMessageAsJson); + var change = JsonSerializer.Deserialize(args.WebMessageAsJson); if (change.type == "bold") { diff --git a/Wino.Mail/Helpers/JsonHelpers.cs b/Wino.Mail/Helpers/JsonHelpers.cs deleted file mode 100644 index c04ecfcc..00000000 --- a/Wino.Mail/Helpers/JsonHelpers.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading.Tasks; - -using Newtonsoft.Json; - -namespace Wino.Helpers -{ - public static class JsonHelpers - { - public static async Task ToObjectAsync(string value) - { - return await Task.Run(() => - { - return JsonConvert.DeserializeObject(value); - }); - } - - public static async Task StringifyAsync(object value) - { - return await Task.Run(() => - { - return JsonConvert.SerializeObject(value); - }); - } - } -} diff --git a/Wino.Mail/Helpers/SettingsStorageExtensions.cs b/Wino.Mail/Helpers/SettingsStorageExtensions.cs index a566e891..b18fdeeb 100644 --- a/Wino.Mail/Helpers/SettingsStorageExtensions.cs +++ b/Wino.Mail/Helpers/SettingsStorageExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.IO; using System.Threading.Tasks; - using Windows.Storage; using Windows.Storage.Streams; @@ -11,87 +9,6 @@ namespace Wino.Helpers // More details regarding storing and retrieving app data at https://docs.microsoft.com/windows/uwp/app-settings/store-and-retrieve-app-data public static class SettingsStorageExtensions { - private const string FileExtension = ".json"; - - public static bool IsRoamingStorageAvailable(this ApplicationData appData) - { - return appData.RoamingStorageQuota == 0; - } - - public static async Task SaveAsync(this StorageFolder folder, string name, T content) - { - var file = await folder.CreateFileAsync(GetFileName(name), CreationCollisionOption.ReplaceExisting); - var fileContent = await JsonHelpers.StringifyAsync(content); - - await FileIO.WriteTextAsync(file, fileContent); - } - - public static async Task ReadAsync(this StorageFolder folder, string name) - { - if (!File.Exists(Path.Combine(folder.Path, GetFileName(name)))) - { - return default; - } - - var file = await folder.GetFileAsync($"{name}.json"); - var fileContent = await FileIO.ReadTextAsync(file); - - return await JsonHelpers.ToObjectAsync(fileContent); - } - - public static async Task SaveAsync(this ApplicationDataContainer settings, string key, T value) - { - settings.SaveString(key, await JsonHelpers.StringifyAsync(value)); - } - - public static void SaveString(this ApplicationDataContainer settings, string key, string value) - { - settings.Values[key] = value; - } - - public static async Task ReadAsync(this ApplicationDataContainer settings, string key) - { - object obj = null; - - if (settings.Values.TryGetValue(key, out obj)) - { - return await JsonHelpers.ToObjectAsync((string)obj); - } - - return default; - } - - public static async Task SaveFileAsync(this StorageFolder folder, byte[] content, string fileName, CreationCollisionOption options = CreationCollisionOption.ReplaceExisting) - { - if (content == null) - { - throw new ArgumentNullException(nameof(content)); - } - - if (string.IsNullOrEmpty(fileName)) - { - throw new ArgumentException("File name is null or empty. Specify a valid file name", nameof(fileName)); - } - - var storageFile = await folder.CreateFileAsync(fileName, options); - await FileIO.WriteBytesAsync(storageFile, content); - return storageFile; - } - - public static async Task ReadFileAsync(this StorageFolder folder, string fileName) - { - var item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false); - - if ((item != null) && item.IsOfType(StorageItemTypes.File)) - { - var storageFile = await folder.GetFileAsync(fileName); - byte[] content = await storageFile.ReadBytesAsync(); - return content; - } - - return null; - } - public static async Task ReadBytesAsync(this StorageFile file) { if (file != null) @@ -110,10 +27,5 @@ namespace Wino.Helpers return null; } - - private static string GetFileName(string name) - { - return string.Concat(name, FileExtension); - } } } diff --git a/Wino.Mail/Views/ComposePage.xaml.cs b/Wino.Mail/Views/ComposePage.xaml.cs index 61ef5c96..e65ddc26 100644 --- a/Wino.Mail/Views/ComposePage.xaml.cs +++ b/Wino.Mail/Views/ComposePage.xaml.cs @@ -11,7 +11,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml.Controls; using Microsoft.Web.WebView2.Core; using MimeKit; -using Newtonsoft.Json; using Windows.ApplicationModel.DataTransfer; using Windows.Foundation; using Windows.Storage; @@ -29,6 +28,8 @@ using Wino.Mail.ViewModels.Data; using Wino.Views.Abstract; using CommunityToolkit.WinUI.Controls; using Wino.Helpers; +using System.Text.Json; + #if NET8_0 using Microsoft.UI.Xaml; @@ -215,7 +216,7 @@ namespace Wino.Views imageDataURLs.Add(await GetDataURL(file)); } - await InvokeScriptSafeAsync($"insertImages({JsonConvert.SerializeObject(imageDataURLs)});"); + await InvokeScriptSafeAsync($"insertImages({JsonSerializer.Serialize(imageDataURLs)});"); } } // State should be reset even when an exception occurs, otherwise the UI will be stuck in a dragging state. @@ -328,7 +329,7 @@ namespace Wino.Views string script = functionName + "("; for (int i = 0; i < parameters.Length; i++) { - script += JsonConvert.SerializeObject(parameters[i]); + script += JsonSerializer.Serialize(parameters[i]); if (i < parameters.Length - 1) { script += ", "; @@ -459,7 +460,7 @@ namespace Wino.Views { var editorContent = await InvokeScriptSafeAsync("GetHTMLContent();"); - return JsonConvert.DeserializeObject(editorContent); + return JsonSerializer.Deserialize(editorContent); }); var underlyingThemeService = App.Current.Services.GetService(); @@ -483,7 +484,7 @@ namespace Wino.Views private void ScriptMessageReceived(CoreWebView2 sender, CoreWebView2WebMessageReceivedEventArgs args) { - var change = JsonConvert.DeserializeObject(args.WebMessageAsJson); + var change = JsonSerializer.Deserialize(args.WebMessageAsJson); if (change.type == "bold") { diff --git a/Wino.Mail/Views/MailRenderingPage.xaml.cs b/Wino.Mail/Views/MailRenderingPage.xaml.cs index 1f100014..324692c4 100644 --- a/Wino.Mail/Views/MailRenderingPage.xaml.cs +++ b/Wino.Mail/Views/MailRenderingPage.xaml.cs @@ -1,12 +1,12 @@ using System; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; using Microsoft.AppCenter.Crashes; using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml.Controls; using Microsoft.Web.WebView2.Core; -using Newtonsoft.Json; using Windows.System; using Wino.Core.Domain; @@ -78,7 +78,7 @@ namespace Wino.Views string script = functionName + "("; for (int i = 0; i < parameters.Length; i++) { - script += JsonConvert.SerializeObject(parameters[i]); + script += JsonSerializer.Serialize(parameters[i]); if (i < parameters.Length - 1) { script += ", "; diff --git a/Wino.Mail/Wino.Mail.csproj b/Wino.Mail/Wino.Mail.csproj index a4d3b720..dd0d2858 100644 --- a/Wino.Mail/Wino.Mail.csproj +++ b/Wino.Mail/Wino.Mail.csproj @@ -298,7 +298,6 @@ AccountCreationDialog.xaml -