From 467b1733f3e219a70bbde4fb6d117d397835a167 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Thu, 6 Aug 2020 17:45:30 -0700 Subject: [PATCH 01/10] Replace Newtonsoft.Json with the new .Net JsonSerializer. --- .../Microsoft.Toolkit.Services.csproj | 2 +- .../Microsoft.Toolkit.Services.rd.xml | 6 ++ .../Services/LinkedIn/LinkedInDataProvider.cs | 16 ++- .../Services/LinkedIn/LinkedInParser.cs | 10 +- .../MicrosoftTranslator/AzureAuthToken.cs | 9 +- .../MicrosoftTranslator/ErrorResponse.cs | 16 ++- .../MicrosoftTranslator/ServiceLanguage.cs | 4 +- .../MicrosoftTranslator/TranslatorService.cs | 13 ++- .../Services/Twitter/Tweet.cs | 58 +++++------ .../Services/Twitter/TweetParser.cs | 4 +- .../Twitter/TwitterCoordinatesConverter.cs | 97 ++++++++++++++++--- .../Services/Twitter/TwitterDataProvider.cs | 8 +- .../Services/Twitter/TwitterDirectMessage.cs | 22 ++--- .../Services/Twitter/TwitterEntities.cs | 14 +-- .../Services/Twitter/TwitterError.cs | 6 +- .../Services/Twitter/TwitterErrors.cs | 4 +- .../Services/Twitter/TwitterExtended.cs | 4 +- .../Twitter/TwitterExtendedEntities.cs | 4 +- .../Services/Twitter/TwitterGeoData.cs | 6 +- .../Services/Twitter/TwitterHashtag.cs | 6 +- .../Services/Twitter/TwitterMedia.cs | 26 ++--- .../Twitter/TwitterMediaAdditionalInfo.cs | 10 +- .../Services/Twitter/TwitterMediaSizeData.cs | 8 +- .../Services/Twitter/TwitterMediaSizes.cs | 10 +- .../Services/Twitter/TwitterMediaVideoInfo.cs | 8 +- .../Twitter/TwitterMediaVideoVariants.cs | 8 +- .../Services/Twitter/TwitterOAuthRequest.cs | 33 ++++--- .../Twitter/TwitterOAuthRequestExtensions.cs | 8 -- .../Services/Twitter/TwitterParser.cs | 8 +- .../Services/Twitter/TwitterPlace.cs | 18 ++-- .../Twitter/TwitterPlaceBoundingBox.cs | 7 +- .../Services/Twitter/TwitterPoll.cs | 8 +- .../Services/Twitter/TwitterPollOptions.cs | 6 +- .../Services/Twitter/TwitterSearchParser.cs | 4 +- .../Twitter/TwitterStreamDeletedEvent.cs | 6 +- .../Services/Twitter/TwitterStreamEvent.cs | 9 +- .../Services/Twitter/TwitterSymbol.cs | 6 +- .../Services/Twitter/TwitterUrl.cs | 12 +-- .../Services/Twitter/TwitterUrlUnwound.cs | 10 +- .../Services/Twitter/TwitterUser.cs | 66 ++++++------- .../Services/Twitter/TwitterUserMention.cs | 4 +- .../Twitter/TwitterUserStreamParser.cs | 41 +++----- .../Services/Weibo/WeiboDataProvider.cs | 15 ++- .../Services/Weibo/WeiboError.cs | 6 +- .../Services/Weibo/WeiboGeoInfo.cs | 6 +- .../Services/Weibo/WeiboImage.cs | 8 +- .../Services/Weibo/WeiboOAuthRequest.cs | 23 +++-- .../Weibo/WeiboOAuthRequestExtensions.cs | 8 -- .../Services/Weibo/WeiboParser.cs | 8 +- .../Services/Weibo/WeiboStatus.cs | 36 +++---- .../Services/Weibo/WeiboStatusParser.cs | 16 +-- .../Services/Weibo/WeiboUser.cs | 28 +++--- .../DifferencesGen.csproj | 5 - .../Data/GitHub.cs | 4 +- .../Data/PhotosDataSource.cs | 4 +- .../Microsoft.Toolkit.Uwp.SampleApp.csproj | 4 +- .../Models/GitHubRelease.cs | 14 +-- .../Models/LandingPageLink.cs | 6 +- .../Models/LandingPageLinks.cs | 8 +- .../Models/LandingPageResource.cs | 8 +- .../Models/Sample.cs | 10 +- .../Models/Samples.cs | 9 +- .../Pages/About.xaml.cs | 7 +- .../EnumValuesExtensionPage.xaml.cs | 4 +- .../InAppNotificationPage.xaml.cs | 4 +- .../MarkdownParser/MarkdownParserPage.xaml.cs | 12 ++- .../MicrosoftTranslatorPage.xaml.cs | 17 ++-- .../landingPageLinks.json | 4 - .../Microsoft.Toolkit.Uwp.Services.csproj | 3 - .../Microsoft.Toolkit.Uwp.Services.rd.xml | 1 + .../Facebook/FacebookRequestSource.cs | 4 +- .../Services/Facebook/FacebookService.cs | 22 ++++- ...initeCanvasVirtualDrawingSurface.Render.cs | 22 +++-- .../InfiniteCanvas/Drawables/InkDrawable.cs | 2 +- .../JsonConverters/SerializableStroke.cs | 2 +- ... Microsoft.Toolkit.Uwp.UI.Controls.rd.xml} | 1 + .../ObjectStorage/JsonObjectSerializer.cs | 6 +- .../Microsoft.Toolkit.Uwp.csproj | 4 +- .../Properties/Microsoft.Toolkit.Uwp.rd.xml | 6 ++ .../Microsoft.Windows.Toolkit.rd.xml | 33 ------- .../Helpers/Test_StorageHelper.cs | 8 +- UnitTests/UnitTests.UWP/UnitTests.UWP.csproj | 3 + 82 files changed, 542 insertions(+), 474 deletions(-) create mode 100644 Microsoft.Toolkit.Services/Properties/Microsoft.Toolkit.Services.rd.xml rename Microsoft.Toolkit.Uwp.UI.Controls/Properties/{Microsoft.Windows.Toolkit.UI.Controls.rd.xml => Microsoft.Toolkit.Uwp.UI.Controls.rd.xml} (68%) create mode 100644 Microsoft.Toolkit.Uwp/Properties/Microsoft.Toolkit.Uwp.rd.xml delete mode 100644 Microsoft.Toolkit.Uwp/Properties/Microsoft.Windows.Toolkit.rd.xml diff --git a/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj b/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj index 1db59a5b434..a7d3225ee7e 100644 --- a/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj +++ b/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj @@ -30,7 +30,7 @@ - + diff --git a/Microsoft.Toolkit.Services/Properties/Microsoft.Toolkit.Services.rd.xml b/Microsoft.Toolkit.Services/Properties/Microsoft.Toolkit.Services.rd.xml new file mode 100644 index 00000000000..9f5b9bd9498 --- /dev/null +++ b/Microsoft.Toolkit.Services/Properties/Microsoft.Toolkit.Services.rd.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs index f852688bc57..cf07a1c305e 100644 --- a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs +++ b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs @@ -7,9 +7,9 @@ using System.Diagnostics; using System.Net.Http; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Toolkit.Services.Core; -using Newtonsoft.Json.Linq; #if WINRT using Microsoft.Toolkit.Services.PlatformSpecific.Uwp; @@ -81,7 +81,8 @@ public LinkedInDataProvider(LinkedInOAuthTokens tokens, LinkedInPermissions requ throw new ArgumentException("Missing callback uri"); } - if (!Enum.IsDefined(typeof(LinkedInPermissions), requiredPermissions)) + // Check if outside the bounds of the LinkedInPermissions Enum + if (requiredPermissions < 0 || requiredPermissions > (LinkedInPermissions)15) { throw new ArgumentException("Error retrieving required permissions"); } @@ -278,9 +279,14 @@ private async Task GetAccessTokenAsync(LinkedInOAuthTokens tokens, strin { using (var response = await client.SendAsync(request).ConfigureAwait(false)) { - var jsonString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var json = JObject.Parse(jsonString); - return json.GetValue("access_token").Value(); + using (var jsonStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + { + using (var jsonDoc = await JsonDocument.ParseAsync(jsonStream).ConfigureAwait(false)) + { + var value = jsonDoc.RootElement.GetProperty("access_token"); + return value.GetString(); + } + } } } } diff --git a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInParser.cs b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInParser.cs index 583385bd1ee..4e145764452 100644 --- a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInParser.cs +++ b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInParser.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; namespace Microsoft.Toolkit.Services.LinkedIn { @@ -24,11 +24,11 @@ public IEnumerable Parse(string data) try { - results = JsonConvert.DeserializeObject>(data); + results = JsonSerializer.Deserialize>(data); } - catch (JsonSerializationException) + catch (JsonException) { - T linkedInResult = JsonConvert.DeserializeObject(data); + T linkedInResult = JsonSerializer.Deserialize(data); results = new List { linkedInResult }; } @@ -42,7 +42,7 @@ public IEnumerable Parse(string data) /// Returns string data. public string Parse(T dataToShare) { - return JsonConvert.SerializeObject(dataToShare, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); + return JsonSerializer.Serialize(dataToShare, typeof(T), new JsonSerializerOptions { IgnoreNullValues = true }); } } } diff --git a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs index 4ac141da9e0..32dff4c0c74 100644 --- a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs +++ b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs @@ -4,8 +4,8 @@ using System; using System.Net.Http; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; namespace Microsoft.Toolkit.Services.MicrosoftTranslator { @@ -24,6 +24,9 @@ internal class AzureAuthToken /// private static readonly Uri ServiceUrl = new Uri("https://api.cognitive.microsoft.com/sts/v1.0/issueToken"); + // TODO + // private static readonly Uri ServiceUrl = new Uri(THIS SHOULD BE A PARAMETER NOW); + /// /// After obtaining a valid token, this class will cache it for this duration. /// Use a duration of 8 minutes, which is less than the actual token lifetime of 10 minutes. @@ -99,8 +102,8 @@ public async Task GetAccessTokenAsync() if (!response.IsSuccessStatusCode) { - var error = JsonConvert.DeserializeObject(content); - throw new TranslatorServiceException(error.Message); + var error = JsonSerializer.Deserialize(content); + throw new TranslatorServiceException(error?.Error?.Message); } _storedTokenTime = DateTime.Now; diff --git a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ErrorResponse.cs b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ErrorResponse.cs index 3d9e9038495..870ee897f0e 100644 --- a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ErrorResponse.cs +++ b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ErrorResponse.cs @@ -2,21 +2,27 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Text.Json.Serialization; + namespace Microsoft.Toolkit.Services.MicrosoftTranslator { +#pragma warning disable SA1402 // File may only contain a single type /// /// Holds information about an error occurred while accessing Microsoft Translator Service. /// internal class ErrorResponse + { + [JsonPropertyName("error")] + public Error Error { get; set; } + } + + internal class Error { /// /// Gets or sets the error message. /// + [JsonPropertyName("message")] public string Message { get; set; } - - /// - /// Gets or sets the HTTP status code. - /// - public int StatusCode { get; set; } } +#pragma warning restore SA1402 // File may only contain a single type } diff --git a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ServiceLanguage.cs b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ServiceLanguage.cs index 6053cebb865..abed597f9bd 100644 --- a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ServiceLanguage.cs +++ b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/ServiceLanguage.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.MicrosoftTranslator { @@ -30,7 +30,7 @@ public class ServiceLanguage /// /// Gets the directionality, which is rtl for right-to-left languages or ltr for left-to-right languages. /// - [JsonProperty("dir")] + [JsonPropertyName("dir")] public string Directionality { get; } /// diff --git a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs index ac3680b266a..83c9a008956 100644 --- a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs +++ b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs @@ -8,9 +8,8 @@ using System.Linq; using System.Net.Http; using System.Net.Http.Headers; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Microsoft.Toolkit.Services.MicrosoftTranslator { @@ -113,7 +112,7 @@ public async Task> DetectLanguagesWithResp var response = await client.SendAsync(request).ConfigureAwait(false); var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var responseContent = JsonConvert.DeserializeObject>(content); + var responseContent = JsonSerializer.Deserialize>(content); return responseContent; } } @@ -144,8 +143,8 @@ public async Task> GetLanguageNamesAsync(string lan var response = await client.SendAsync(request).ConfigureAwait(false); var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var jsonContent = JToken.Parse(content)["translation"]; - var responseContent = JsonConvert.DeserializeObject>(jsonContent.ToString()).ToList(); + var jsonContent = JsonDocument.Parse(content).RootElement.GetProperty("translation"); + var responseContent = JsonSerializer.Deserialize>(jsonContent.ToString()).ToList(); responseContent.ForEach(r => r.Value.Code = r.Key); return responseContent.Select(r => r.Value).OrderBy(r => r.Name).ToList(); @@ -221,7 +220,7 @@ public async Task> TranslateWithResponseAsync(I var response = await client.SendAsync(request).ConfigureAwait(false); var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var responseContent = JsonConvert.DeserializeObject>(content); + var responseContent = JsonSerializer.Deserialize>(content); return responseContent; } } @@ -254,7 +253,7 @@ private HttpRequestMessage CreateHttpRequest(string uriString, HttpMethod method if (content != null) { - var jsonRequest = JsonConvert.SerializeObject(content); + var jsonRequest = JsonSerializer.Serialize(content); var requestContent = new StringContent(jsonRequest, System.Text.Encoding.UTF8, JsonMediaType); request.Content = requestContent; } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/Tweet.cs b/Microsoft.Toolkit.Services/Services/Twitter/Tweet.cs index 97d2613aa02..c0dea2d0092 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/Tweet.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/Tweet.cs @@ -4,7 +4,7 @@ using System; using System.Globalization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -18,19 +18,19 @@ public class Tweet : Toolkit.Parsers.SchemaBase, ITwitterResult /// /// Gets or sets time item was created. /// - [JsonProperty("created_at")] + [JsonPropertyName("created_at")] public string CreatedAt { get; set; } /// /// Gets or sets item Id. /// - [JsonProperty("id_str")] + [JsonPropertyName("id_str")] public string Id { get; set; } /// /// Gets or sets text of the tweet (handles both 140 and 280 characters) /// - [JsonProperty("text")] + [JsonPropertyName("text")] public string Text { get { return _text ?? FullText; } @@ -40,13 +40,13 @@ public string Text /// /// Gets or sets text of the tweet (280 characters). /// - [JsonProperty("full_text")] + [JsonPropertyName("full_text")] private string FullText { get; set; } /// /// Gets or sets display text range (indexes of tweet text without RT and leading user mentions) /// - [JsonProperty("display_text_range")] + [JsonPropertyName("display_text_range")] public int[] DisplayTextRange { get; set; } /// @@ -54,68 +54,68 @@ public string Text /// (true when tweet is longer than 140 characters) /// This entity may be deprecated - it never seems to be set to true. /// - [JsonProperty("truncated")] + [JsonPropertyName("truncated")] public bool IsTruncated { get; set; } /// /// Gets or sets attached content of the tweet /// - [JsonProperty("entities")] + [JsonPropertyName("entities")] public TwitterEntities Entities { get; set; } /// /// Gets or sets extended attached content of the tweet /// - [JsonProperty("extended_entities")] + [JsonPropertyName("extended_entities")] public TwitterExtendedEntities ExtendedEntities { get; set; } /// /// Gets or sets tweet source (client or website used) /// - [JsonProperty("source")] + [JsonPropertyName("source")] public string Source { get; set; } /// /// Gets or sets in_reply_to_screen_name /// - [JsonProperty("in_reply_to_screen_name")] + [JsonPropertyName("in_reply_to_screen_name")] public string InReplyToScreenName { get; set; } /// /// Gets or sets in_reply_to_status_id_str /// - [JsonProperty("in_reply_to_status_id_str")] + [JsonPropertyName("in_reply_to_status_id_str")] public string InReplyToStatusId { get; set; } /// /// Gets or sets in_reply_to_user_id_str /// - [JsonProperty("in_reply_to_user_id_str")] + [JsonPropertyName("in_reply_to_user_id_str")] public string InReplyToUserId { get; set; } /// /// Gets or sets user who posted the status. /// - [JsonProperty("user")] + [JsonPropertyName("user")] public TwitterUser User { get; set; } /// /// Gets or sets geo coordinates (latitude and longitude) returned by Twitter for some locations /// - [JsonProperty("coordinates")] + [JsonPropertyName("coordinates")] [JsonConverter(typeof(TwitterCoordinatesConverter))] public TwitterCoordinates Coordinates { get; set; } /// /// Gets or sets the Place object returned by Twitter for some locations /// - [JsonProperty("place")] + [JsonPropertyName("place")] public TwitterPlace Place { get; set; } /// /// Gets or sets the Retweeted Tweet /// - [JsonProperty("retweeted_status")] + [JsonPropertyName("retweeted_status")] public Tweet RetweetedStatus { get; set; } /// @@ -138,25 +138,25 @@ public DateTime CreationDate /// /// Gets or sets quoted_status /// - [JsonProperty("quoted_status")] + [JsonPropertyName("quoted_status")] public Tweet QuotedStatus { get; set; } /// /// Gets or sets quoted_status_id_str /// - [JsonProperty("quoted_status_id_str")] + [JsonPropertyName("quoted_status_id_str")] public string QuotedStatusId { get; set; } /// /// Gets or sets quoted_status_permalink /// - [JsonProperty("quoted_status_permalink")] + [JsonPropertyName("quoted_status_permalink")] public TwitterUrl QuotedStatusPermalink { get; set; } /// /// Gets or sets approximate count of tweets quoting tweet /// - [JsonProperty("quote_count")] + [JsonPropertyName("quote_count")] public int QuoteCount { get; set; } /// @@ -165,49 +165,49 @@ public DateTime CreationDate /// /// Premium and Enterprise API access only /// - [JsonProperty("reply_count")] + [JsonPropertyName("reply_count")] public int ReplyCount { get; set; } /// /// Gets or sets number of times tweet has been retweeted /// - [JsonProperty("retweet_count")] + [JsonPropertyName("retweet_count")] public int RetweetCount { get; set; } /// /// Gets or sets number of times tweet has been liked /// - [JsonProperty("favorite_count")] + [JsonPropertyName("favorite_count")] public int FavoriteCount { get; set; } /// /// Gets or sets a value indicating whether or not logged-in user has liked tweet /// - [JsonProperty("favorited")] + [JsonPropertyName("favorited")] public bool Favorited { get; set; } /// /// Gets or sets a value indicating whether or not logged-in user has retweeted tweet /// - [JsonProperty("retweeted")] + [JsonPropertyName("retweeted")] public bool Retweeted { get; set; } /// /// Gets or sets a value indicating whether URL in tweet has been flagged for sensitive content /// - [JsonProperty("possibly_sensitive")] + [JsonPropertyName("possibly_sensitive")] public bool Sensitive { get; set; } /// /// Gets or sets stream filter of tweet /// - [JsonProperty("filter_level")] + [JsonPropertyName("filter_level")] public string FilterLevel { get; set; } /// /// Gets or sets BCP 47 language identifier of tweet content /// - [JsonProperty("lang")] + [JsonPropertyName("lang")] public string Language { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TweetParser.cs b/Microsoft.Toolkit.Services/Services/Twitter/TweetParser.cs index 711e95808f0..26a544cb6f8 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TweetParser.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TweetParser.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; namespace Microsoft.Toolkit.Services.Twitter { @@ -24,7 +24,7 @@ public IEnumerable Parse(string data) return null; } - return JsonConvert.DeserializeObject>(data); + return JsonSerializer.Deserialize>(data); } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs index 73375d98fab..5a53501286a 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs @@ -3,41 +3,104 @@ // See the LICENSE file in the project root for more information. using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { - internal class TwitterCoordinatesConverter : JsonConverter + internal class TwitterCoordinatesConverter : JsonConverter { + private readonly JsonEncodedText latitudeName = JsonEncodedText.Encode("Latitude"); + private readonly JsonEncodedText longitudeName = JsonEncodedText.Encode("Longitude"); + public override bool CanConvert(Type objectType) { return false; } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + private readonly JsonConverter _doubleConverter; + + public TwitterCoordinatesConverter(JsonSerializerOptions options) + { + if (options?.GetConverter(typeof(double)) is JsonConverter doubleConverter) + { + _doubleConverter = doubleConverter; + } + else + { + throw new InvalidOperationException(); + } + } + + public override TwitterCoordinates Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { try { - if (reader.TokenType != JsonToken.StartObject) + if (reader.TokenType != JsonTokenType.StartObject) { return null; } - var jObject = JObject.Load(reader); - var jCoordinates = jObject["coordinates"] as JArray; + double latitude = default; + bool latitudeSet = false; - if (jCoordinates.Count != 2) + double longitude = default; + bool longitudeSet = false; + + // Get the first property. + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName) { - return null; + throw new JsonException(); + } + + if (reader.ValueTextEquals(latitudeName.EncodedUtf8Bytes)) + { + latitude = ReadProperty(ref reader, options); + latitudeSet = true; + } + else if (reader.ValueTextEquals(longitudeName.EncodedUtf8Bytes)) + { + longitude = ReadProperty(ref reader, options); + longitudeSet = true; + } + else + { + throw new JsonException(); } - var twitterCoordinates = new TwitterCoordinates + // Get the second property. + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName) { - Latitude = (double)jCoordinates[0], - Longitude = (double)jCoordinates[1] + throw new JsonException(); + } + + if (latitudeSet && reader.ValueTextEquals(longitudeName.EncodedUtf8Bytes)) + { + longitude = ReadProperty(ref reader, options); + } + else if (longitudeSet && reader.ValueTextEquals(latitudeName.EncodedUtf8Bytes)) + { + latitude = ReadProperty(ref reader, options); + } + else + { + throw new JsonException(); + } + + reader.Read(); + + if (reader.TokenType != JsonTokenType.EndObject) + { + throw new JsonException(); + } + + return new TwitterCoordinates + { + Latitude = latitude, + Longitude = longitude }; - return twitterCoordinates; } catch { @@ -45,7 +108,13 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist } } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + private double ReadProperty(ref Utf8JsonReader reader, JsonSerializerOptions options) + { + reader.Read(); + return _doubleConverter.Read(ref reader, typeof(double), options); + } + + public override void Write(Utf8JsonWriter writer, TwitterCoordinates value, JsonSerializerOptions options) { throw new NotImplementedException(); } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs index a6eda59f07e..b594fcba563 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs @@ -10,9 +10,9 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Toolkit.Services.Core; -using Newtonsoft.Json; #if WINRT using System.Runtime.InteropServices.WindowsRuntime; @@ -140,7 +140,7 @@ public async Task GetUserAsync(string screenName = null) TwitterOAuthRequest request = new TwitterOAuthRequest(); rawResult = await request.ExecuteGetAsync(uri, _tokens, _signatureManager); - return JsonConvert.DeserializeObject(rawResult); + return JsonSerializer.Deserialize(rawResult); } catch (UserNotFoundException) { @@ -150,7 +150,7 @@ public async Task GetUserAsync(string screenName = null) { if (!string.IsNullOrEmpty(rawResult)) { - var errors = JsonConvert.DeserializeObject(rawResult); + var errors = JsonSerializer.Deserialize(rawResult); throw new TwitterException { Errors = errors }; } @@ -191,7 +191,7 @@ public async Task> GetUserTimeLineAsync(string scr { if (!string.IsNullOrEmpty(rawResult)) { - var errors = JsonConvert.DeserializeObject(rawResult); + var errors = JsonSerializer.Deserialize(rawResult); throw new TwitterException { Errors = errors }; } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterDirectMessage.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterDirectMessage.cs index 7ffe9355f1c..803c9b7404d 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterDirectMessage.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterDirectMessage.cs @@ -4,7 +4,7 @@ using System; using System.Globalization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -17,70 +17,70 @@ public class TwitterDirectMessage : ITwitterResult /// Gets or sets the direct message id. /// /// The direct message id. - [JsonProperty(PropertyName = "id")] + [JsonPropertyName("id")] public decimal Id { get; set; } /// /// Gets or sets the sender id. /// /// The sender id. - [JsonProperty(PropertyName = "sender_id")] + [JsonPropertyName("sender_id")] public decimal SenderId { get; set; } /// /// Gets or sets the direct message text. /// /// The direct message text. - [JsonProperty(PropertyName = "text")] + [JsonPropertyName("text")] public string Text { get; set; } /// /// Gets or sets the recipient id. /// /// The recipient id. - [JsonProperty(PropertyName = "recipient_id")] + [JsonPropertyName("recipient_id")] public decimal RecipientId { get; set; } /// /// Gets or sets the created date. /// /// The created date. - [JsonProperty(PropertyName = "created_at")] + [JsonPropertyName("created_at")] public string CreatedAt { get; set; } /// /// Gets or sets the name of the sender screen. /// /// The name of the sender screen. - [JsonProperty(PropertyName = "sender_screen_name")] + [JsonPropertyName("sender_screen_name")] public string SenderScreenName { get; set; } /// /// Gets or sets the name of the recipient screen. /// /// The name of the recipient screen. - [JsonProperty(PropertyName = "recipient_screen_name")] + [JsonPropertyName("recipient_screen_name")] public string RecipientScreenName { get; set; } /// /// Gets or sets the sender. /// /// The sender. - [JsonProperty(PropertyName = "sender")] + [JsonPropertyName("sender")] public TwitterUser Sender { get; set; } /// /// Gets or sets the recipient. /// /// The recipient. - [JsonProperty(PropertyName = "recipient")] + [JsonPropertyName("recipient")] public TwitterUser Recipient { get; set; } /// /// Gets or sets the entities. /// /// The entities. - [JsonProperty(PropertyName = "entities")] + [JsonPropertyName("entities")] public TwitterEntities Entities { get; set; } /// diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterEntities.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterEntities.cs index 0e489429c48..d4e76c90a12 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterEntities.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterEntities.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -15,35 +15,35 @@ public class TwitterEntities /// Gets or sets Hashtags array of the tweet. /// This array will be empty if no Hashtags are present. /// - [JsonProperty("Hashtags")] + [JsonPropertyName("Hashtags")] public TwitterHashtag[] Hashtags { get; set; } /// /// Gets or sets Symbols array of the tweet. /// This array will be empty if no Symbols are present. /// - [JsonProperty("Symbols")] + [JsonPropertyName("Symbols")] public TwitterSymbol[] Symbols { get; set; } /// /// Gets or sets Media array of the tweet. /// This array will not exist if no media is present. /// - [JsonProperty("media")] + [JsonPropertyName("media")] public TwitterMedia[] Media { get; set; } /// /// Gets or sets Urls array of the tweet. /// This array will be empty if no Urls are present. /// - [JsonProperty("urls")] + [JsonPropertyName("urls")] public TwitterUrl[] Urls { get; set; } /// /// Gets or sets array of usernames mentioned in the tweet. /// This array will be empty if no usernames are mentioned. /// - [JsonProperty("user_mentions")] + [JsonPropertyName("user_mentions")] public TwitterUserMention[] UserMentions { get; set; } /// @@ -51,7 +51,7 @@ public class TwitterEntities /// This array will not exist if no poll is present. /// This array will always have one poll. /// - [JsonProperty("polls")] + [JsonPropertyName("polls")] public TwitterPoll Poll { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterError.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterError.cs index 66e1abf291c..3df83ff3c61 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterError.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterError.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,13 +14,13 @@ public class TwitterError /// /// Gets or sets error code /// - [JsonProperty("code")] + [JsonPropertyName("code")] public int Code { get; set; } /// /// Gets or sets error message /// - [JsonProperty("message")] + [JsonPropertyName("message")] public string Message { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterErrors.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterErrors.cs index 2ccad80ee64..801c7485bcc 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterErrors.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterErrors.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,7 +14,7 @@ public class TwitterErrors /// /// Gets or sets the list of errors /// - [JsonProperty("errors")] + [JsonPropertyName("errors")] public TwitterError[] Errors { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtended.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtended.cs index c0bd10a7019..d9cca155f90 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtended.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtended.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,7 +14,7 @@ public class TwitterExtended /// /// Gets or sets the text of the tweet (280 characters). /// - [JsonProperty("full_text")] + [JsonPropertyName("full_text")] public string FullText { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtendedEntities.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtendedEntities.cs index 9f912a1f027..6f4ae88d54c 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtendedEntities.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterExtendedEntities.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,7 +14,7 @@ public class TwitterExtendedEntities /// /// Gets or sets Media of the tweet. /// - [JsonProperty("media")] + [JsonPropertyName("media")] public TwitterMedia[] Media { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterGeoData.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterGeoData.cs index 125dc904cc6..977090f6f36 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterGeoData.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterGeoData.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Globalization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -19,7 +19,7 @@ public class TwitterGeoData /// /// Gets or sets the type of data /// - [JsonProperty("type")] + [JsonPropertyName("type")] public string DataType { get; set; } /// @@ -43,7 +43,7 @@ public string DisplayCoordinates /// /// Gets or sets the coordinates of the geographic data /// - [JsonProperty("coordinates")] + [JsonPropertyName("coordinates")] public string[] Coordinates { get; set; } /// diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterHashtag.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterHashtag.cs index 6dc329569b8..d5350ede07a 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterHashtag.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterHashtag.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,13 +14,13 @@ public class TwitterHashtag /// /// Gets or sets indices of hashtag location in tweet string. /// - [JsonProperty("indices")] + [JsonPropertyName("indices")] public int[] Indices { get; set; } /// /// Gets or sets hashtag text, excluding #. /// - [JsonProperty("text")] + [JsonPropertyName("text")] public string Text { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMedia.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMedia.cs index e6846337bb6..2ebe86dacf7 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMedia.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMedia.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,73 +14,73 @@ public class TwitterMedia /// /// Gets or sets ID as string. /// - [JsonProperty("id_str")] + [JsonPropertyName("id_str")] public string Id { get; set; } /// /// Gets or sets indices array. /// - [JsonProperty("indices")] + [JsonPropertyName("indices")] public int[] Indices { get; set; } /// /// Gets or sets MediaUrl (direct link to image). /// - [JsonProperty("media_url")] + [JsonPropertyName("media_url")] public string MediaUrl { get; set; } /// /// Gets or sets HTTPS MediaUrl. /// - [JsonProperty("media_url_https")] + [JsonPropertyName("media_url_https")] public string MediaUrlHttps { get; set; } /// /// Gets or sets t.co shortened tweet Url. /// - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } /// /// Gets or sets DisplayUrl (pics.twitter.com Url). /// - [JsonProperty("display_url")] + [JsonPropertyName("display_url")] public string DisplayUrl { get; set; } /// /// Gets or sets DisplayUrl (pics.twitter.com Url). /// - [JsonProperty("expanded_url")] + [JsonPropertyName("expanded_url")] public string ExpandedUrl { get; set; } /// /// Gets or sets MediaType - photo, animated_gif, or video /// - [JsonProperty("type")] + [JsonPropertyName("type")] public string MediaType { get; set; } /// /// Gets or sets size array /// - [JsonProperty("sizes")] + [JsonPropertyName("sizes")] public TwitterMediaSizes Sizes { get; set; } /// /// Gets or sets the SourceId - tweet ID of media's original tweet /// - [JsonProperty("source_status_id_str")] + [JsonPropertyName("source_status_id_str")] public string SourceIdStr { get; set; } /// /// Gets or sets metadata for video attached to tweet /// - [JsonProperty("video_info")] + [JsonPropertyName("video_info")] public TwitterMediaVideoInfo VideoInfo { get; set; } /// /// Gets or sets extended metadata for video attached to tweet. /// - [JsonProperty("additional_media_info")] + [JsonPropertyName("additional_media_info")] public TwitterMediaAdditionalInfo AdditionalMediaInfo { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaAdditionalInfo.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaAdditionalInfo.cs index 048844380c0..4ded7817d98 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaAdditionalInfo.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaAdditionalInfo.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,25 +14,25 @@ public class TwitterMediaAdditionalInfo /// /// Gets or sets title of video /// - [JsonProperty("title")] + [JsonPropertyName("title")] public string Title { get; set; } /// /// Gets or sets description of video /// - [JsonProperty("description")] + [JsonPropertyName("description")] public string Description { get; set; } /// /// Gets or sets a value indicating whether video is embeddable /// - [JsonProperty("embeddable")] + [JsonPropertyName("embeddable")] public bool Embeddable { get; set; } /// /// Gets or sets a value indicating whether "monetizable" /// - [JsonProperty("monetizable")] + [JsonPropertyName("monetizable")] public bool Monetizable { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizeData.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizeData.cs index db91c1502e9..7c787eb4af4 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizeData.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizeData.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,19 +14,19 @@ public class TwitterMediaSizeData /// /// Gets or sets width integer. /// - [JsonProperty("w")] + [JsonPropertyName("w")] public int Width { get; set; } /// /// Gets or sets height integer. /// - [JsonProperty("h")] + [JsonPropertyName("h")] public int Height { get; set; } /// /// Gets or sets resize string. /// - [JsonProperty("resize")] + [JsonPropertyName("resize")] public string Resize { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizes.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizes.cs index d6a4cb73a04..dbffbf70cf2 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizes.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaSizes.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,25 +14,25 @@ public class TwitterMediaSizes /// /// Gets or sets small metadata. /// - [JsonProperty("small")] + [JsonPropertyName("small")] public TwitterMediaSizeData Small { get; set; } /// /// Gets or sets thumbnail metadata. /// - [JsonProperty("thumb")] + [JsonPropertyName("thumb")] public TwitterMediaSizeData Thumb { get; set; } /// /// Gets or sets large metadata. /// - [JsonProperty("large")] + [JsonPropertyName("large")] public TwitterMediaSizeData Large { get; set; } /// /// Gets or sets medium metadata. /// - [JsonProperty("medium")] + [JsonPropertyName("medium")] public TwitterMediaSizeData Medium { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoInfo.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoInfo.cs index 1fde7a7789d..88904902388 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoInfo.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoInfo.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,19 +14,19 @@ public class TwitterMediaVideoInfo /// /// Gets or sets video aspect ratio (width, height) /// - [JsonProperty("aspect_ratio")] + [JsonPropertyName("aspect_ratio")] public int[] AspectRatio { get; set; } /// /// Gets or sets duration of video in milliseconds /// - [JsonProperty("duration_millis")] + [JsonPropertyName("duration_millis")] public int Duration { get; set; } /// /// Gets or sets video variants for different codecs, bitrates, etc. /// - [JsonProperty("variants")] + [JsonPropertyName("variants")] public TwitterMediaVideoVariants[] Variants { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoVariants.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoVariants.cs index ad3b8915450..38301583bd5 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoVariants.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterMediaVideoVariants.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,19 +14,19 @@ public class TwitterMediaVideoVariants /// /// Gets or sets video bitrate in bits-per-second /// - [JsonProperty("bitrate")] + [JsonPropertyName("bitrate")] public int Bitrate { get; set; } /// /// Gets or sets the MIME type of the video /// - [JsonProperty("content_type")] + [JsonPropertyName("content_type")] public string ContentType { get; set; } /// /// Gets or sets the direct URL for the video variant /// - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs index 3cab762951d..7ad7f835c50 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs @@ -8,10 +8,9 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Toolkit.Services.Core; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Microsoft.Toolkit.Services.Twitter { @@ -79,17 +78,18 @@ public async Task ExecuteGetStreamAsync(Uri requestUri, TwitterOAuthTokens token using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) { response.ThrowIfNotValid(); - var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - - using (var reader = new StreamReader(responseStream)) + using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) { - while (!_abort && !reader.EndOfStream) + using (var reader = new StreamReader(responseStream)) { - var result = reader.ReadLine(); - - if (!string.IsNullOrEmpty(result)) + while (!_abort && !reader.EndOfStream) { - callback?.Invoke(result); + var result = reader.ReadLine(); + + if (!string.IsNullOrEmpty(result)) + { + callback?.Invoke(result); + } } } } @@ -139,7 +139,7 @@ public async Task ExecutePostAsync(Uri requestUri, TwitterOAuthTokens to /// String result. public async Task ExecutePostMultipartAsync(Uri requestUri, TwitterOAuthTokens tokens, string boundary, byte[] content, ISignatureManager signatureManager) { - JToken mediaId = null; + JsonElement mediaId = default; try { @@ -160,10 +160,11 @@ public async Task ExecutePostMultipartAsync(Uri requestUri, TwitterOAuth using (var response = await client.SendAsync(request).ConfigureAwait(false)) { response.ThrowIfNotValid(); - string jsonResult = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - - JObject jObj = JObject.Parse(jsonResult); - mediaId = jObj["media_id_string"]; + using (var jsonResult = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + { + var jObj = await JsonDocument.ParseAsync(jsonResult).ConfigureAwait(false); + mediaId = jObj.RootElement.GetProperty("media_id_string"); + } } } } @@ -182,7 +183,7 @@ private string ProcessErrors(string content) { if (content.StartsWith("{\"errors\":")) { - var errors = JsonConvert.DeserializeObject(content); + var errors = JsonSerializer.Deserialize(content); throw new TwitterException { Errors = errors }; } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequestExtensions.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequestExtensions.cs index 71a29f45145..7d48701f2ea 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequestExtensions.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequestExtensions.cs @@ -2,16 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.IO; -using System.IO.Compression; using System.Net; using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Microsoft.Toolkit.Services.Core; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Microsoft.Toolkit.Services.Twitter { diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterParser.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterParser.cs index 1fc118c2c1e..3404467d836 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterParser.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterParser.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; namespace Microsoft.Toolkit.Services.Twitter { @@ -28,12 +28,12 @@ IEnumerable Toolkit.Parsers.IParser.Parse(string data) try { - return JsonConvert.DeserializeObject>(data); + return JsonSerializer.Deserialize>(data); } - catch (JsonSerializationException) + catch (JsonException) { List items = new List(); - items.Add(JsonConvert.DeserializeObject(data)); + items.Add(JsonSerializer.Deserialize(data)); return items; } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlace.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlace.cs index 516e74aa80a..0b5f451130b 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlace.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlace.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,49 +14,49 @@ public class TwitterPlace /// /// Gets or sets the ID of the place /// - [JsonProperty("id")] + [JsonPropertyName("id")] public string Id { get; set; } /// /// Gets or sets the URL of additional place metadata /// - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } /// /// Gets or sets the place type. /// - [JsonProperty("place_type")] + [JsonPropertyName("place_type")] public string PlaceType { get; set; } /// /// Gets or sets the place name. /// - [JsonProperty("name")] + [JsonPropertyName("name")] public string Name { get; set; } /// /// Gets or sets the full, human-readable place name. /// - [JsonProperty("full_name")] + [JsonPropertyName("full_name")] public string FullName { get; set; } /// /// Gets or sets the shortened country code (e.g. US) for the place. /// - [JsonProperty("country_code")] + [JsonPropertyName("country_code")] public string CountryCode { get; set; } /// /// Gets or sets the name of the country for the place. /// - [JsonProperty("country")] + [JsonPropertyName("country")] public string Country { get; set; } /// /// Gets or sets the bounding box coordinates of a location. /// - [JsonProperty("bounding_box")] + [JsonPropertyName("bounding_box")] public TwitterPlaceBoundingBox BoundingBox { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlaceBoundingBox.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlaceBoundingBox.cs index 9e20940bf28..fb39af14c3b 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlaceBoundingBox.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPlaceBoundingBox.cs @@ -3,8 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Globalization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -16,13 +15,13 @@ public class TwitterPlaceBoundingBox /// /// Gets or sets the bounding box coordinates of the tweet's geolocation data. /// - [JsonProperty("coordinates")] + [JsonPropertyName("coordinates")] public List> Coordinates { get; set; } /// /// Gets or sets the coordinate type. Polygon for a bounding box, Point for an exact coordinate. /// - [JsonProperty("type")] + [JsonPropertyName("type")] public string Type { get; set; } /// diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPoll.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPoll.cs index a632d269e38..24f65ee1cbe 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPoll.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPoll.cs @@ -4,7 +4,7 @@ using System; using System.Globalization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -16,19 +16,19 @@ public class TwitterPoll /// /// Gets or sets poll questions. /// - [JsonProperty("options")] + [JsonPropertyName("options")] public TwitterPollOptions[] Options { get; set; } /// /// Gets or sets end timestamp as a string. /// - [JsonProperty("end_datetime")] + [JsonPropertyName("end_datetime")] public string EndDateTime { get; set; } /// /// Gets or sets duration of the poll in minutes. /// - [JsonProperty("duration_minutes")] + [JsonPropertyName("duration_minutes")] public string DurationMinutes { get; set; } /// diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPollOptions.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPollOptions.cs index e7d27ab8a8b..af44d214905 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterPollOptions.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterPollOptions.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,13 +14,13 @@ public class TwitterPollOptions /// /// Gets or sets int value of the poll position. /// - [JsonProperty("position")] + [JsonPropertyName("position")] public int Position { get; set; } /// /// Gets or sets text of the poll question. /// - [JsonProperty("text")] + [JsonPropertyName("text")] public string Text { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterSearchParser.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterSearchParser.cs index 7a91992539d..263cddbdf46 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterSearchParser.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterSearchParser.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; +using System.Text.Json; namespace Microsoft.Toolkit.Services.Twitter { @@ -25,7 +25,7 @@ public IEnumerable Parse(string data) return null; } - var result = JsonConvert.DeserializeObject(data); + var result = JsonSerializer.Deserialize(data); return result.Statuses.ToList(); } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamDeletedEvent.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamDeletedEvent.cs index a0f0c3db63a..fa52090e83d 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamDeletedEvent.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamDeletedEvent.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -15,14 +15,14 @@ public class TwitterStreamDeletedEvent : ITwitterResult /// Gets or sets the user id of the event. This is always the user who initiated the event. /// /// The user Id. - [JsonProperty(PropertyName = "user_id_str")] + [JsonPropertyName("user_id_str")] public string UserId { get; set; } /// /// Gets or sets the id of the event. This is the tweet that was affected. /// /// The tweet Id. - [JsonProperty(PropertyName = "id_str")] + [JsonPropertyName("id_str")] public string Id { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamEvent.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamEvent.cs index d27be43828a..8bd3b68b2bc 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamEvent.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterStreamEvent.cs @@ -4,8 +4,7 @@ using System; using System.Globalization; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -18,8 +17,8 @@ public class TwitterStreamEvent : ITwitterResult /// Gets or sets the type of the event. /// /// The type of the event. - [JsonProperty(PropertyName = "event")] - [JsonConverter(typeof(StringEnumConverter))] + [JsonPropertyName("event")] + [JsonConverter(typeof(JsonStringEnumConverter))] public TwitterStreamEventType EventType { get; set; } /// @@ -44,7 +43,7 @@ public class TwitterStreamEvent : ITwitterResult /// Gets or sets the creation date. /// /// The creation date. - [JsonProperty(PropertyName = "created_at")] + [JsonPropertyName("created_at")] public string CreatedAt { get; set; } /// diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterSymbol.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterSymbol.cs index 9473ba97fc6..dcac308e6b1 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterSymbol.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterSymbol.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,13 +14,13 @@ public class TwitterSymbol /// /// Gets or sets indices of hashtag location in tweet string. /// - [JsonProperty("indices")] + [JsonPropertyName("indices")] public int[] Indices { get; set; } /// /// Gets or sets hashtag text, excluding #. /// - [JsonProperty("text")] + [JsonPropertyName("text")] public string Text { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrl.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrl.cs index dae1bd7b778..ebadd1348bc 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrl.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrl.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,31 +14,31 @@ public class TwitterUrl /// /// Gets or sets DisplayUrl of the Url. /// - [JsonProperty("display_url")] + [JsonPropertyName("display_url")] public string DisplayUrl { get; set; } /// /// Gets or sets ExpandedUrl of the Url. /// - [JsonProperty("expanded_url")] + [JsonPropertyName("expanded_url")] public string ExpandedUrl { get; set; } /// /// Gets or sets indices position of the tweet. /// - [JsonProperty("indices")] + [JsonPropertyName("indices")] public int[] Indices { get; set; } /// /// Gets or sets unwound Url metadata position of the tweet. /// - [JsonProperty("unwound")] + [JsonPropertyName("unwound")] public TwitterUrlUnwound Unwound { get; set; } /// /// Gets or sets t.co Url of the tweet. /// - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrlUnwound.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrlUnwound.cs index 095e0aec6a5..2f202320621 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrlUnwound.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUrlUnwound.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,25 +14,25 @@ public class TwitterUrlUnwound /// /// Gets or sets fully unwound url. /// - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } /// /// Gets or sets status of unwind; if anything but 200 the data's bad. /// - [JsonProperty("status")] + [JsonPropertyName("status")] public int Status { get; set; } /// /// Gets or sets HTML title for url. /// - [JsonProperty("title")] + [JsonPropertyName("title")] public string Title { get; set; } /// /// Gets or sets description of link. /// - [JsonProperty("description")] + [JsonPropertyName("description")] public string Description { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUser.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUser.cs index b3484b95663..94219faa81a 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUser.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUser.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,194 +14,194 @@ public class TwitterUser /// /// Gets or sets user Id. /// - [JsonProperty("id_str")] + [JsonPropertyName("id_str")] public string Id { get; set; } /// /// Gets or sets user name. /// - [JsonProperty("name")] + [JsonPropertyName("name")] public string Name { get; set; } /// /// Gets or sets user screen name. /// - [JsonProperty("screen_name")] + [JsonPropertyName("screen_name")] public string ScreenName { get; set; } /// /// Gets or sets profile location. /// - [JsonProperty("location")] + [JsonPropertyName("location")] public string Location { get; set; } /// /// Gets or sets profile url. /// - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } /// /// Gets or sets profile description. /// - [JsonProperty("description")] + [JsonPropertyName("description")] public string Description { get; set; } /// /// Gets or sets a value indicating whether protected status of user. /// - [JsonProperty("protected")] + [JsonPropertyName("protected")] public bool Protected { get; set; } /// /// Gets or sets a value indicating whether account is verified (blue checkmark). /// - [JsonProperty("verified")] + [JsonPropertyName("verified")] public bool Verified { get; set; } /// /// Gets or sets followers count. /// - [JsonProperty("followers_count")] + [JsonPropertyName("followers_count")] public int FollowersCount { get; set; } /// /// Gets or sets count of accounts user is following. /// - [JsonProperty("friends_count")] + [JsonPropertyName("friends_count")] public int FriendsCount { get; set; } /// /// Gets or sets count of public lists user is a member of. /// - [JsonProperty("listed_count")] + [JsonPropertyName("listed_count")] public int ListedCount { get; set; } /// /// Gets or sets total count of tweets user has liked. /// - [JsonProperty("favourites_count")] + [JsonPropertyName("favourites_count")] public int FavoritesCount { get; set; } /// /// Gets or sets total count of tweets (including retweets) posted by user. /// - [JsonProperty("statuses_count")] + [JsonPropertyName("statuses_count")] public int StatusesCount { get; set; } /// /// Gets or sets a value indicating whether geotagging is enabled. /// This determines whether or not to geotag the user's posts. /// - [JsonProperty("geo_enabled")] + [JsonPropertyName("geo_enabled")] public bool GeoEnabled { get; set; } /// /// Gets or sets BCP 47 language code according to user's account settings. /// - [JsonProperty("lang")] + [JsonPropertyName("lang")] public string Lang { get; set; } /// /// Gets or sets a value indicating whether contributor mode is enabled. /// - [JsonProperty("contributors_enabled")] + [JsonPropertyName("contributors_enabled")] public bool ContributorsEnabled { get; set; } /// /// Gets or sets profile background color (web hex value). /// - [JsonProperty("profile_background_color")] + [JsonPropertyName("profile_background_color")] public string ProfileBackgroundColor { get; set; } /// /// Gets or sets profile background image url. /// - [JsonProperty("profile_background_image_url")] + [JsonPropertyName("profile_background_image_url")] public string ProfileBackgroundImageUrl { get; set; } /// /// Gets or sets profile background image url using https. /// - [JsonProperty("profile_background_image_url_https")] + [JsonPropertyName("profile_background_image_url_https")] public string ProfileBackgroundImageUrlHttps { get; set; } /// /// Gets or sets a value indicating whether profile background image is tiled. /// - [JsonProperty("profile_background_tile")] + [JsonPropertyName("profile_background_tile")] public bool ProfileBackgroundTile { get; set; } /// /// Gets or sets profile banner url. /// - [JsonProperty("profile_banner_url")] + [JsonPropertyName("profile_banner_url")] public string ProfileBannerUrl { get; set; } /// /// Gets or sets profile image url. /// - [JsonProperty("profile_image_url")] + [JsonPropertyName("profile_image_url")] public string ProfileImageUrl { get; set; } /// /// Gets or sets profile image url using https. /// - [JsonProperty("profile_image_url_https")] + [JsonPropertyName("profile_image_url_https")] public string ProfileImageUrlHttps { get; set; } /// /// Gets or sets profile link color (web hex value). /// - [JsonProperty("profile_link_color")] + [JsonPropertyName("profile_link_color")] public string ProfileLinkColor { get; set; } /// /// Gets or sets profile sidebar border color (web hex value). /// - [JsonProperty("profile_sidebar_border_color")] + [JsonPropertyName("profile_sidebar_border_color")] public string ProfileSidebarBorderColor { get; set; } /// /// Gets or sets profile sidebar fill color (web hex value). /// - [JsonProperty("profile_sidebar_fill_color")] + [JsonPropertyName("profile_sidebar_fill_color")] public string ProfileSidebarFillColor { get; set; } /// /// Gets or sets profile text color (web hex value). /// - [JsonProperty("profile_text_color")] + [JsonPropertyName("profile_text_color")] public string ProfileTextColor { get; set; } /// /// Gets or sets a value indicating whether the user has selected to use their uploaded background image in their profile. /// - [JsonProperty("profile_use_background_image")] + [JsonPropertyName("profile_use_background_image")] public bool ProfileUseBackgroundImage { get; set; } /// /// Gets or sets a value indicating whether or not user is using the default profile theme and background. /// - [JsonProperty("default_profile")] + [JsonPropertyName("default_profile")] public bool DefaultProfile { get; set; } /// /// Gets or sets a value indicating whether or not the user is using the default profile image. /// - [JsonProperty("default_profile_image")] + [JsonPropertyName("default_profile_image")] public bool DefaultProfileImage { get; set; } /// /// Gets or sets "withheld in" countries. /// - [JsonProperty("withheld_in_countries")] + [JsonPropertyName("withheld_in_countries")] public string[] WithheldInCountries { get; set; } /// /// Gets or sets withheld scope (status or profile). /// - [JsonProperty("withheld_scope")] + [JsonPropertyName("withheld_scope")] public string WithheldScope { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserMention.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserMention.cs index c8797dd9caa..aa7b6ac861a 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserMention.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserMention.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Twitter { @@ -14,7 +14,7 @@ public class TwitterUserMention : TwitterUser /// /// Gets or sets the start and end position of the user mention /// - [JsonProperty("indices")] + [JsonPropertyName("indices")] public int[] Indices { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserStreamParser.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserStreamParser.cs index e0148295af9..f1d5560184d 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserStreamParser.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterUserStreamParser.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json; namespace Microsoft.Toolkit.Services.Twitter { @@ -24,55 +23,47 @@ public ITwitterResult Parse(string data) return null; } - var obj = (JObject)JsonConvert.DeserializeObject(data); + var obj = JsonDocument.Parse(data); - var friends = obj.SelectToken("friends", false); - if (friends != null && friends.HasValues) + if (obj.RootElement.TryGetProperty("friends", out var friends) && friends.GetArrayLength() > 0) { return null; } - var delete = obj.SelectToken("delete", false); - if (delete != null) + if (obj.RootElement.TryGetProperty("delete", out var delete)) { - var deletedStatus = delete.SelectToken("status", false); - if (deletedStatus != null && deletedStatus.HasValues) + if (delete.TryGetProperty("status", out var deletedStatus) && deletedStatus.GetArrayLength() > 0) { - return JsonConvert.DeserializeObject(deletedStatus.ToString()); + return JsonSerializer.Deserialize(deletedStatus.ToString()); } - var deletedDirectMessage = delete.SelectToken("direct_message", false); - if (deletedDirectMessage != null && deletedDirectMessage.HasValues) + if (delete.TryGetProperty("direct_message", out var deletedDirectMessage) && deletedDirectMessage.GetArrayLength() > 0) { - return JsonConvert.DeserializeObject(deletedDirectMessage.ToString()); + return JsonSerializer.Deserialize(deletedDirectMessage.ToString()); } } - var events = obj.SelectToken("event", false); - if (events != null) + if (obj.RootElement.TryGetProperty("event", out var events)) { - var targetobject = obj.SelectToken("target_object", false); Tweet endtargetobject = null; - if (targetobject?.SelectToken("user", false) != null) + if (obj.RootElement.TryGetProperty("target_object", out var targetobject) && targetobject.TryGetProperty("user", out _)) { - endtargetobject = JsonConvert.DeserializeObject(targetobject.ToString()); + endtargetobject = JsonSerializer.Deserialize(targetobject.ToString()); } - var endevent = JsonConvert.DeserializeObject(obj.ToString()); + var endevent = JsonSerializer.Deserialize(obj.ToString()); endevent.TargetObject = endtargetobject; return endevent; } - var user = obj.SelectToken("user", false); - if (user != null && user.HasValues) + if (obj.RootElement.TryGetProperty("user", out var user) && user.GetArrayLength() > 0) { - return JsonConvert.DeserializeObject(obj.ToString()); + return JsonSerializer.Deserialize(obj.ToString()); } - var directMessage = obj.SelectToken("direct_message", false); - if (directMessage != null && directMessage.HasValues) + if (obj.RootElement.TryGetProperty("direct_message", out var directMessage) && directMessage.GetArrayLength() > 0) { - return JsonConvert.DeserializeObject(directMessage.ToString()); + return JsonSerializer.Deserialize(directMessage.ToString()); } return null; diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboDataProvider.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboDataProvider.cs index 3dd6d59a8ac..101ca54c73e 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboDataProvider.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboDataProvider.cs @@ -8,12 +8,11 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Toolkit.Parsers; using Microsoft.Toolkit.Services.Core; using Microsoft.Toolkit.Services.OAuth; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; #if WINRT using System.Runtime.InteropServices.WindowsRuntime; @@ -235,15 +234,15 @@ private async Task ExchangeRequestTokenForAccessTokenAsync(string webAuthR data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } - JObject jObject = JObject.Parse(data); + var jObject = JsonDocument.Parse(data); - string accessToken = jObject["access_token"].ToObject(); + string accessToken = jObject.RootElement.GetProperty("access_token").GetString(); if (string.IsNullOrEmpty(accessToken)) { throw new NullReferenceException("The accessToken is null."); } - long uid = jObject["uid"].ToObject(); + long uid = jObject.RootElement.GetProperty("uid").GetInt64(); Uid = uid; _tokens.AccessToken = accessToken; @@ -276,7 +275,7 @@ public async Task GetUserAsync(string screenName = null) WeiboOAuthRequest request = new WeiboOAuthRequest(); rawResult = await request.ExecuteGetAsync(uri, _tokens); - return JsonConvert.DeserializeObject(rawResult); + return JsonSerializer.Deserialize(rawResult); } catch (UserNotFoundException) { @@ -286,7 +285,7 @@ public async Task GetUserAsync(string screenName = null) { if (!string.IsNullOrEmpty(rawResult)) { - var error = JsonConvert.DeserializeObject(rawResult); + var error = JsonSerializer.Deserialize(rawResult); throw new WeiboException { Error = error }; } @@ -327,7 +326,7 @@ public async Task> GetUserTimeLineAsync(string scr { if (!string.IsNullOrEmpty(rawResult)) { - var errors = JsonConvert.DeserializeObject(rawResult); + var errors = JsonSerializer.Deserialize(rawResult); throw new WeiboException { Error = errors }; } diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboError.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboError.cs index 8c078b8db10..0a426bc9cb1 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboError.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboError.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Weibo { @@ -14,13 +14,13 @@ public class WeiboError /// /// Gets or sets error code /// - [JsonProperty("error_code")] + [JsonPropertyName("error_code")] public int Code { get; set; } /// /// Gets or sets error message /// - [JsonProperty("error")] + [JsonPropertyName("error")] public string Message { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboGeoInfo.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboGeoInfo.cs index e247a2f9da6..d7a19d136ec 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboGeoInfo.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboGeoInfo.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Services.Weibo { @@ -14,13 +14,13 @@ public class WeiboGeoInfo /// /// Gets the type of geographic information /// - [JsonProperty("type")] + [JsonPropertyName("type")] public string Type { get; internal set; } /// /// Gets the coordinates /// - [JsonProperty("coordinates")] + [JsonPropertyName("coordinates")] public double[] Coordinates { get; internal set; } /// diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboImage.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboImage.cs index d8c33c241e2..dcb56e4b04e 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboImage.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboImage.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Weibo { @@ -14,19 +14,19 @@ public class WeiboImage /// /// Gets or sets the url of the attached image in thumbnail size. /// - [JsonProperty("thumbnail_pic")] + [JsonPropertyName("thumbnail_pic")] public string ThumbnailImageUrl { get; set; } /// /// Gets or sets the url of the attached image in medium size. /// - [JsonProperty("bmiddle_pic")] + [JsonPropertyName("bmiddle_pic")] public string MediumImageUrl { get; set; } /// /// Gets or sets the url of the attached image in original size. /// - [JsonProperty("original_pic")] + [JsonPropertyName("original_pic")] public string OriginalImageUrl { get; set; } } } diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs index 45ce1d25575..011c9d8bc44 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs @@ -7,9 +7,9 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Toolkit.Services.OAuth; -using Newtonsoft.Json; namespace Microsoft.Toolkit.Services.Weibo { @@ -97,7 +97,10 @@ public async Task ExecutePostAsync(Uri requestUri, WeiboOAuthTokens { if (response.StatusCode == HttpStatusCode.OK) { - return JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); + using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + { + return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); + } } else { @@ -153,7 +156,10 @@ public async Task ExecutePostMultipartAsync(Uri requestUri, WeiboOA { if (response.StatusCode == HttpStatusCode.OK) { - return JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); + using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + { + return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); + } } else { @@ -180,10 +186,15 @@ private string ProcessError(string content) { if (content.StartsWith("{\"error\":")) { - WeiboError error = JsonConvert.DeserializeObject(content, new JsonSerializerSettings() + WeiboError error; + try { - Error = (sender, args) => throw new JsonException("Invalid Weibo error response!", args.ErrorContext.Error) - }); + error = JsonSerializer.Deserialize(content); + } + catch (JsonException e) + { + throw new JsonException("Invalid Weibo error response!", e); + } throw new WeiboException { Error = error }; } diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequestExtensions.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequestExtensions.cs index 7f7cbb31d76..0a49a6bd2a2 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequestExtensions.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequestExtensions.cs @@ -2,16 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.IO; -using System.IO.Compression; using System.Net; using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Microsoft.Toolkit.Services.Core; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Microsoft.Toolkit.Services.Weibo { diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboParser.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboParser.cs index cb3d998308d..7691ea269ad 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboParser.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboParser.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; namespace Microsoft.Toolkit.Services.Weibo { @@ -28,12 +28,12 @@ IEnumerable Toolkit.Parsers.IParser.Parse(string data) try { - return JsonConvert.DeserializeObject>(data); + return JsonSerializer.Deserialize>(data); } - catch (JsonSerializationException) + catch (JsonException) { List items = new List(); - items.Add(JsonConvert.DeserializeObject(data)); + items.Add(JsonSerializer.Deserialize(data)); return items; } } diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatus.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatus.cs index a3c26c3de9e..7e8c06a8f7f 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatus.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatus.cs @@ -4,8 +4,8 @@ using System; using System.Globalization; +using System.Text.Json.Serialization; using Microsoft.Toolkit.Services.Services.Weibo; -using Newtonsoft.Json; namespace Microsoft.Toolkit.Services.Weibo { @@ -17,7 +17,7 @@ public class WeiboStatus : Toolkit.Parsers.SchemaBase /// /// Gets or sets time item was created. /// - [JsonProperty("created_at")] + [JsonPropertyName("created_at")] public string CreatedAt { get; set; } /// @@ -40,13 +40,13 @@ public DateTime CreationDate /// /// Gets or sets item Id. /// - [JsonProperty("id")] + [JsonPropertyName("id")] public string Id { get; set; } /// /// Gets or sets text of the status (handles both 140 and 280 characters) /// - [JsonProperty("text")] + [JsonPropertyName("text")] public string Text { get; set; } /// @@ -54,85 +54,85 @@ public DateTime CreationDate /// (true when Weibo status is longer than 140 characters) /// This entity may be deprecated - it never seems to be set to true. /// - [JsonProperty("truncated")] + [JsonPropertyName("truncated")] public bool IsTruncated { get; set; } /// /// Gets or sets status source (client or website used) /// - [JsonProperty("source")] + [JsonPropertyName("source")] public string Source { get; set; } /// /// Gets or sets in_reply_to_screen_name /// - [JsonProperty("in_reply_to_screen_name")] + [JsonPropertyName("in_reply_to_screen_name")] public string InReplyToScreenName { get; set; } /// /// Gets or sets in_reply_to_status_id /// - [JsonProperty("in_reply_to_status_id")] + [JsonPropertyName("in_reply_to_status_id")] public string InReplyToStatusId { get; set; } /// /// Gets or sets in_reply_to_user_id /// - [JsonProperty("in_reply_to_user_id")] + [JsonPropertyName("in_reply_to_user_id")] public string InReplyToUserId { get; set; } /// /// Gets or sets user who posted the status. /// - [JsonProperty("user")] + [JsonPropertyName("user")] public WeiboUser User { get; set; } /// /// Gets or sets the Reposted Weibo status /// - [JsonProperty("retweeted_status")] + [JsonPropertyName("retweeted_status")] public WeiboStatus RepostedStatus { get; set; } /// /// Gets or sets the repost count /// - [JsonProperty("reposts_count")] + [JsonPropertyName("reposts_count")] public int RepostCount { get; set; } /// /// Gets or sets the comment count /// - [JsonProperty("comments_count")] + [JsonPropertyName("comments_count")] public int CommentCount { get; set; } /// /// Gets or sets the url of the attached image in thumbnail size. /// - [JsonProperty("thumbnail_pic")] + [JsonPropertyName("thumbnail_pic")] public string ThumbnailImageUrl { get; set; } /// /// Gets or sets the url of the attached image in medium size. /// - [JsonProperty("bmiddle_pic")] + [JsonPropertyName("bmiddle_pic")] public string MediumImageUrl { get; set; } /// /// Gets or sets the url of the attached image in original size. /// - [JsonProperty("original_pic")] + [JsonPropertyName("original_pic")] public string OriginalImageUrl { get; set; } /// /// Gets or sets attached images array of the weibo. /// - [JsonProperty("pic_urls")] + [JsonPropertyName("pic_urls")] public WeiboImage[] AttachedImages { get; set; } /// /// Gets or sets the geographic information. /// - [JsonProperty("geo")] + [JsonPropertyName("geo")] public WeiboGeoInfo GeographicInfo { get; set; } /// diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatusParser.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatusParser.cs index 09f0ae084f9..cdeac82859a 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatusParser.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboStatusParser.cs @@ -2,14 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Toolkit.Services.Weibo; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json; namespace Microsoft.Toolkit.Services.Weibo { @@ -30,14 +24,14 @@ public IEnumerable Parse(string data) return null; } - JObject rawObject = JObject.Parse(data); + var rawObject = JsonDocument.Parse(data); - IList rawStatuses = rawObject["statuses"].Children().ToList(); + var rawStatuses = rawObject.RootElement.GetProperty("statuses"); IList statuses = new List(); - foreach (JToken result in rawStatuses) + foreach (var rawStatus in rawStatuses.EnumerateArray()) { - WeiboStatus searchResult = result.ToObject(); + WeiboStatus searchResult = JsonSerializer.Deserialize(rawStatus.ToString()); statuses.Add(searchResult); } diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboUser.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboUser.cs index 82e55fdeae1..242ca0058e7 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboUser.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboUser.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Services.Weibo { @@ -14,79 +14,79 @@ public class WeiboUser /// /// Gets or sets user Id. /// - [JsonProperty("id")] + [JsonPropertyName("id")] public string Id { get; set; } /// /// Gets or sets user name. /// - [JsonProperty("name")] + [JsonPropertyName("name")] public string Name { get; set; } /// /// Gets or sets user screen name. /// - [JsonProperty("screen_name")] + [JsonPropertyName("screen_name")] public string ScreenName { get; set; } /// /// Gets or sets profile location. /// - [JsonProperty("location")] + [JsonPropertyName("location")] public string Location { get; set; } /// /// Gets or sets profile url. /// - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } /// /// Gets or sets profile description. /// - [JsonProperty("description")] + [JsonPropertyName("description")] public string Description { get; set; } /// /// Gets or sets profile image url. /// - [JsonProperty("profile_image_url")] + [JsonPropertyName("profile_image_url")] public string ProfileImageUrl { get; set; } /// /// Gets or sets high resolution profile image url. /// - [JsonProperty("avatar_large")] + [JsonPropertyName("avatar_large")] public string HighResolutionProfileImageUrl { get; set; } /// /// Gets or sets followers count. /// - [JsonProperty("followers_count")] + [JsonPropertyName("followers_count")] public int FollowersCount { get; set; } /// /// Gets or sets count of accounts user is following. /// - [JsonProperty("friends_count")] + [JsonPropertyName("friends_count")] public int FriendsCount { get; set; } /// /// Gets or sets total count of statuses user has liked. /// - [JsonProperty("favourites_count")] + [JsonPropertyName("favourites_count")] public int FavoritesCount { get; set; } /// /// Gets or sets total count of Weibo statuses (including reposted statuses) posted by user. /// - [JsonProperty("statuses_count")] + [JsonPropertyName("statuses_count")] public int StatusesCount { get; set; } /// /// Gets or sets a value indicating whether account is verified (blue checkmark). /// - [JsonProperty("verified")] + [JsonPropertyName("verified")] public bool Verified { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.PlatformDifferencesGen/DifferencesGen.csproj b/Microsoft.Toolkit.Uwp.PlatformDifferencesGen/DifferencesGen.csproj index e2726cf8cc5..8cacd579958 100644 --- a/Microsoft.Toolkit.Uwp.PlatformDifferencesGen/DifferencesGen.csproj +++ b/Microsoft.Toolkit.Uwp.PlatformDifferencesGen/DifferencesGen.csproj @@ -53,11 +53,6 @@ - - - 10.0.3 - - diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Data/GitHub.cs b/Microsoft.Toolkit.Uwp.SampleApp/Data/GitHub.cs index d1322f0595d..9a8996727ea 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Data/GitHub.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Data/GitHub.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; using Windows.Web.Http; namespace Microsoft.Toolkit.Uwp.SampleApp.Data @@ -31,7 +31,7 @@ public static async Task> GetPublishedReleases() var uri = $"{_root}/repos/{_repoOwner}/{_repoName}/releases"; var result = await client.GetStringAsync(new Uri(uri)); - _releases = JsonConvert.DeserializeObject>(result).Take(5).ToList(); + _releases = JsonSerializer.Deserialize>(result).Take(5).ToList(); } } catch (Exception) diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Data/PhotosDataSource.cs b/Microsoft.Toolkit.Uwp.SampleApp/Data/PhotosDataSource.cs index 90eceab697e..a3350c0eca4 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Data/PhotosDataSource.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Data/PhotosDataSource.cs @@ -7,8 +7,8 @@ using System.Collections.ObjectModel; using System.IO; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; using Windows.Storage; using Windows.Storage.Streams; using Windows.UI.Xaml.Data; @@ -88,7 +88,7 @@ private static async Task> GetPhotosAsync(bool online private static IEnumerable Parse(string jsonData) { - return JsonConvert.DeserializeObject>(jsonData); + return JsonSerializer.Deserialize>(jsonData); } private static void CheckCacheState(bool online) diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj index 6426c03d171..b872d4720f9 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj +++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj @@ -124,8 +124,8 @@ 2.0.1 - - 10.0.3 + + 4.7.2 1.0.5 diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/GitHubRelease.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/GitHubRelease.cs index e96bac72291..a016bccc80d 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Models/GitHubRelease.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/GitHubRelease.cs @@ -3,30 +3,30 @@ // See the LICENSE file in the project root for more information. using System; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Uwp.SampleApp { public class GitHubRelease { - [JsonProperty("published_at")] + [JsonPropertyName("published_at")] public DateTime Published { get; set; } - [JsonProperty("body")] + [JsonPropertyName("body")] public string Body { get; set; } - [JsonProperty("tag_name")] + [JsonPropertyName("tag_name")] public string Tag { get; set; } - [JsonProperty("name")] + [JsonPropertyName("name")] public string Name { get; set; } public string FullName => $"Version {Name.Replace("v", string.Empty)} notes"; - [JsonProperty("draft")] + [JsonPropertyName("draft")] public bool IsDraft { get; set; } - [JsonProperty("html_url")] + [JsonPropertyName("html_url")] public string Url { get; set; } } } diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLink.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLink.cs index c87d92569ba..05090247425 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLink.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLink.cs @@ -2,16 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Uwp.SampleApp { public class LandingPageLink { - [JsonProperty("title")] + [JsonPropertyName("title")] public string Title { get; set; } - [JsonProperty("url")] + [JsonPropertyName("url")] public string Url { get; set; } } } diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLinks.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLinks.cs index c8fa3afd73f..79297e977ec 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLinks.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageLinks.cs @@ -2,19 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Uwp.SampleApp { public class LandingPageLinks { - [JsonProperty("new-section-title")] + [JsonPropertyName("new-section-title")] public string NewSectionTitle { get; set; } - [JsonProperty("new-samples")] + [JsonPropertyName("new-samples")] public string[] NewSamples { get; set; } - [JsonProperty("resources")] + [JsonPropertyName("resources")] public LandingPageResource[] Resources { get; set; } } } diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageResource.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageResource.cs index 177044e23c3..64fddf52a8b 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageResource.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/LandingPageResource.cs @@ -2,19 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Microsoft.Toolkit.Uwp.SampleApp { public class LandingPageResource { - [JsonProperty("title")] + [JsonPropertyName("title")] public string Title { get; set; } - [JsonProperty("id")] + [JsonPropertyName("id")] public string ID { get; set; } - [JsonProperty("links")] + [JsonPropertyName("links")] public LandingPageLink[] Links { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs index d9aeb0c36ba..d8fef271b2c 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs @@ -12,6 +12,8 @@ using System.Net.Http; using System.Reflection; using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Toolkit.Graph.Converters; @@ -22,7 +24,7 @@ using Microsoft.Toolkit.Uwp.UI.Animations; using Microsoft.Toolkit.Uwp.UI.Controls; using Microsoft.Toolkit.Uwp.UI.Media; -using Newtonsoft.Json; +using Microsoft.UI.Xaml; using Windows.Foundation.Metadata; using Windows.Storage; using Windows.Storage.Streams; @@ -747,7 +749,7 @@ private static async Task GetDocsSHA() { var raw = await response.Content.ReadAsStringAsync(); Debug.WriteLine(raw); - var json = JsonConvert.DeserializeObject(raw); + var json = JsonSerializer.Deserialize(raw); return json?.RefObject?.Sha; } } @@ -762,13 +764,13 @@ private static async Task GetDocsSHA() public class GitRef { - [JsonProperty("object")] + [JsonPropertyName("object")] public GitRefObject RefObject { get; set; } } public class GitRefObject { - [JsonProperty("sha")] + [JsonPropertyName("sha")] public string Sha { get; set; } } } diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/Samples.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/Samples.cs index 45700de0b3a..901bea050e8 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Models/Samples.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/Samples.cs @@ -4,11 +4,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Toolkit.Uwp.Helpers; -using Newtonsoft.Json; namespace Microsoft.Toolkit.Uwp.SampleApp { @@ -56,8 +57,10 @@ public static async Task> GetCategoriesAsync() List allCategories; using (var jsonStream = await StreamHelper.GetPackagedFileStreamAsync("SamplePages/samples.json")) { - var jsonString = await jsonStream.ReadTextAsync(); - allCategories = JsonConvert.DeserializeObject>(jsonString); + allCategories = await JsonSerializer.DeserializeAsync>(jsonStream.AsStream(), new JsonSerializerOptions + { + ReadCommentHandling = JsonCommentHandling.Skip + }); } // Check API diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs index a36dd63aa1d..2040485db8b 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs @@ -5,12 +5,14 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Threading; using System.Threading.Tasks; using Microsoft.Toolkit.Uwp.Helpers; using Microsoft.Toolkit.Uwp.UI.Animations; -using Newtonsoft.Json; using Windows.ApplicationModel; using Windows.UI.Composition; using Windows.UI.Xaml; @@ -202,8 +204,7 @@ private async Task UpdateSections() { using (var jsonStream = await StreamHelper.GetPackagedFileStreamAsync("landingPageLinks.json")) { - var jsonString = await jsonStream.ReadTextAsync(); - var links = JsonConvert.DeserializeObject(jsonString); + var links = await JsonSerializer.DeserializeAsync(jsonStream.AsStream()); var packageVersion = Package.Current.Id.Version; var resource = links.Resources.FirstOrDefault(item => item.ID == "app"); diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/EnumValuesExtensionPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/EnumValuesExtensionPage.xaml.cs index c3313a47588..e85542823fc 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/EnumValuesExtensionPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/EnumValuesExtensionPage.xaml.cs @@ -3,11 +3,11 @@ // See the LICENSE file in the project root for more information. using System; -using Windows.UI; +using Microsoft.Toolkit.Uwp.SampleApp.Enums; using Microsoft.Toolkit.Uwp.UI.Extensions; +using Windows.UI; using Windows.UI.Xaml; using Windows.UI.Xaml.Data; -using Microsoft.Toolkit.Uwp.SampleApp.Enums; namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages { diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/InAppNotification/InAppNotificationPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/InAppNotification/InAppNotificationPage.xaml.cs index cb35082fd6f..79326c89497 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/InAppNotification/InAppNotificationPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/InAppNotification/InAppNotificationPage.xaml.cs @@ -2,11 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Toolkit.Uwp.UI.Controls; -using Microsoft.Toolkit.Uwp.UI.Extensions; using System; using System.Collections.Generic; using System.Windows.Input; +using Microsoft.Toolkit.Uwp.UI.Controls; +using Microsoft.Toolkit.Uwp.UI.Extensions; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/MarkdownParser/MarkdownParserPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/MarkdownParser/MarkdownParserPage.xaml.cs index 024053f55fb..c957626067e 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/MarkdownParser/MarkdownParserPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/MarkdownParser/MarkdownParserPage.xaml.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Toolkit.Parsers.Markdown; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using Windows.UI.Xaml.Controls; namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages @@ -35,7 +35,13 @@ private void UpdateMDResult() var document = new MarkdownDocument(); document.Parse(RawMarkdown.Text); - var json = JsonConvert.SerializeObject(document, Formatting.Indented, new StringEnumConverter()); + var jsonSerializerOptions = new JsonSerializerOptions + { + WriteIndented = true + }; + jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + + var json = JsonSerializer.Serialize(document, typeof(MarkdownDocument), jsonSerializerOptions); MarkdownResult.Text = json; } } diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft Translator Service/MicrosoftTranslatorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft Translator Service/MicrosoftTranslatorPage.xaml.cs index a6b1d4d492d..d6bedd74ad4 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft Translator Service/MicrosoftTranslatorPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft Translator Service/MicrosoftTranslatorPage.xaml.cs @@ -47,13 +47,18 @@ private async void GetLanguages_OnClick(object sender, RoutedEventArgs e) Languages.ItemsSource = null; - _translatorClient.SubscriptionKey = TranslatorServiceKey.Text; - var languages = await _translatorClient.GetLanguageNamesAsync("en"); - - Languages.ItemsSource = languages; - Languages.SelectedIndex = 0; + try + { + _translatorClient.SubscriptionKey = TranslatorServiceKey.Text; + var languages = await _translatorClient.GetLanguageNamesAsync("en"); - SampleController.Current.DisplayWaitRing = false; + Languages.ItemsSource = languages; + Languages.SelectedIndex = 0; + } + finally + { + SampleController.Current.DisplayWaitRing = false; + } } private async void Translate_OnClick(object sender, RoutedEventArgs e) diff --git a/Microsoft.Toolkit.Uwp.SampleApp/landingPageLinks.json b/Microsoft.Toolkit.Uwp.SampleApp/landingPageLinks.json index 611ac435f58..da4679187e2 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/landingPageLinks.json +++ b/Microsoft.Toolkit.Uwp.SampleApp/landingPageLinks.json @@ -84,10 +84,6 @@ "title": "Version", "url": "http://aka.ms/uwptoolkit" }, - { - "title": "Newtonsoft Json (Dependency)", - "url": "http://www.newtonsoft.com/json" - }, { "title": "ColorCode-Universal (Dependency)", "url": "https://github.com/WilliamABradley/ColorCode-Universal" diff --git a/Microsoft.Toolkit.Uwp.Services/Microsoft.Toolkit.Uwp.Services.csproj b/Microsoft.Toolkit.Uwp.Services/Microsoft.Toolkit.Uwp.Services.csproj index b8407c5f573..1478526a750 100644 --- a/Microsoft.Toolkit.Uwp.Services/Microsoft.Toolkit.Uwp.Services.csproj +++ b/Microsoft.Toolkit.Uwp.Services/Microsoft.Toolkit.Uwp.Services.csproj @@ -10,9 +10,6 @@ - - - diff --git a/Microsoft.Toolkit.Uwp.Services/Properties/Microsoft.Toolkit.Uwp.Services.rd.xml b/Microsoft.Toolkit.Uwp.Services/Properties/Microsoft.Toolkit.Uwp.Services.rd.xml index 154280e96c9..db9172549d9 100644 --- a/Microsoft.Toolkit.Uwp.Services/Properties/Microsoft.Toolkit.Uwp.Services.rd.xml +++ b/Microsoft.Toolkit.Uwp.Services/Properties/Microsoft.Toolkit.Uwp.Services.rd.xml @@ -1,5 +1,6 @@ + diff --git a/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookRequestSource.cs b/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookRequestSource.cs index a53679b9a4a..62a9d27413a 100644 --- a/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookRequestSource.cs +++ b/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookRequestSource.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json; using Windows.Foundation.Collections; using winsdkfb; using winsdkfb.Graph; @@ -58,7 +58,7 @@ public FacebookRequestSource(FacebookDataConfig config, string fields, string li _propertySet = new PropertySet { { "fields", _fields }, { "limit", _limit } }; - _factory = new FBJsonClassFactory(s => JsonConvert.DeserializeObject(s, typeof(T))); + _factory = new FBJsonClassFactory(s => JsonSerializer.Deserialize(s, typeof(T))); // FBPaginatedArray does not allow us to set page size per request so we must go with first supplied - see https://github.com/Microsoft/winsdkfb/issues/221 _paginatedArray = new FBPaginatedArray(_config.Query, _propertySet, _factory); diff --git a/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookService.cs b/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookService.cs index 20ba5566eef..b9ec2c6a4b7 100644 --- a/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookService.cs +++ b/Microsoft.Toolkit.Uwp.Services/Services/Facebook/FacebookService.cs @@ -6,8 +6,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.Foundation.Metadata; @@ -275,7 +275,10 @@ public async Task GetUserPictureInfoAsync() { if (Provider.LoggedIn) { - var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject>); + var factory = new FBJsonClassFactory((s) => + { + return JsonSerializer.Deserialize>(s); + }); PropertySet propertySet = new PropertySet { { "redirect", "0" } }; var singleValue = new FBSingleValue("/me/picture", propertySet, factory); @@ -368,7 +371,10 @@ public async Task GetPhotoByPhotoIdAsync(string photoId) { if (Provider.LoggedIn) { - var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject); + var factory = new FBJsonClassFactory((s) => + { + return JsonSerializer.Deserialize(s); + }); PropertySet propertySet = new PropertySet { { "fields", "images" } }; var singleValue = new FBSingleValue($"/{photoId}", propertySet, factory); @@ -405,7 +411,10 @@ public async Task PostToFeedAsync(string link) var parameters = new PropertySet { { "link", link } }; string path = FBSession.ActiveSession.User.Id + "/feed"; - var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject); + var factory = new FBJsonClassFactory((s) => + { + return JsonSerializer.Deserialize(s); + }); var singleValue = new FBSingleValue(path, parameters, factory); var result = await singleValue.PostAsync(); @@ -487,7 +496,10 @@ public async Task PostPictureToFeedAsync(string title, string pictureNam }; string path = FBSession.ActiveSession.User.Id + "/photos"; - var factory = new FBJsonClassFactory(JsonConvert.DeserializeObject); + var factory = new FBJsonClassFactory((s) => + { + return JsonSerializer.Deserialize(s); + }); var singleValue = new FBSingleValue(path, parameters, factory); var result = await singleValue.PostAsync(); diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs index 18f75ee78d6..da628f5e6ef 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs @@ -5,11 +5,10 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Graphics.Canvas; using Microsoft.Graphics.Canvas.UI.Composition; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Windows.Foundation; using Windows.Graphics; using Windows.Storage; @@ -79,9 +78,10 @@ internal void ClearAll(Rect viewPort) internal string GetSerializedList() { var exportModel = new InkCanvasExportModel { DrawableList = _drawableList, Version = 1 }; - return JsonConvert.SerializeObject(exportModel, Formatting.Indented, new JsonSerializerSettings + return JsonSerializer.Serialize(exportModel, new JsonSerializerOptions { - TypeNameHandling = TypeNameHandling.Auto + // TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto + WriteIndented = true, }); } @@ -92,16 +92,22 @@ internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom) _undoCommands.Clear(); _redoCommands.Clear(); - var token = JToken.Parse(json); + var token = JsonDocument.Parse(json); List newList; - if (token is JArray) + if (token.RootElement.ValueKind == JsonValueKind.Array) { // first sin, because of creating a file without versioning so we have to be able to import without breaking changes. - newList = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }); + newList = JsonSerializer.Deserialize>(json, new JsonSerializerOptions + { + // TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto + }); } else { - newList = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }).DrawableList; + newList = JsonSerializer.Deserialize(json, new JsonSerializerOptions + { + // TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto + }).DrawableList; } foreach (var drawable in newList) diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs index 3a3bc724076..e739e3591bf 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs @@ -6,8 +6,8 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using System.Text.Json.Serialization; using Microsoft.Graphics.Canvas; -using Newtonsoft.Json; using Windows.Foundation; using Windows.UI.Input.Inking; using Windows.UI.Xaml; diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs index dcd0255cb8a..da5a62f68e6 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Numerics; using System.Runtime.Serialization; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using Windows.UI.Input.Inking; namespace Microsoft.Toolkit.Uwp.UI.Controls diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Windows.Toolkit.UI.Controls.rd.xml b/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml similarity index 68% rename from Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Windows.Toolkit.UI.Controls.rd.xml rename to Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml index 69e67475b53..890b5155e78 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Windows.Toolkit.UI.Controls.rd.xml +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml @@ -1,5 +1,6 @@ + diff --git a/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/JsonObjectSerializer.cs b/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/JsonObjectSerializer.cs index 8ce982ddfc0..3f1d52f6fbd 100644 --- a/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/JsonObjectSerializer.cs +++ b/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/JsonObjectSerializer.cs @@ -2,14 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; +using System.Text.Json; namespace Microsoft.Toolkit.Uwp.Helpers { internal class JsonObjectSerializer : IObjectSerializer { - public string Serialize(T value) => JsonConvert.SerializeObject(value); + public string Serialize(T value) => JsonSerializer.Serialize(value); - public T Deserialize(string value) => JsonConvert.DeserializeObject(value); + public T Deserialize(string value) => JsonSerializer.Deserialize(value); } } diff --git a/Microsoft.Toolkit.Uwp/Microsoft.Toolkit.Uwp.csproj b/Microsoft.Toolkit.Uwp/Microsoft.Toolkit.Uwp.csproj index 2a6a6fd40d3..445fb25bbf1 100644 --- a/Microsoft.Toolkit.Uwp/Microsoft.Toolkit.Uwp.csproj +++ b/Microsoft.Toolkit.Uwp/Microsoft.Toolkit.Uwp.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/Microsoft.Toolkit.Uwp/Properties/Microsoft.Toolkit.Uwp.rd.xml b/Microsoft.Toolkit.Uwp/Properties/Microsoft.Toolkit.Uwp.rd.xml new file mode 100644 index 00000000000..c852cb37baa --- /dev/null +++ b/Microsoft.Toolkit.Uwp/Properties/Microsoft.Toolkit.Uwp.rd.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Microsoft.Toolkit.Uwp/Properties/Microsoft.Windows.Toolkit.rd.xml b/Microsoft.Toolkit.Uwp/Properties/Microsoft.Windows.Toolkit.rd.xml deleted file mode 100644 index 2f2bb20c525..00000000000 --- a/Microsoft.Toolkit.Uwp/Properties/Microsoft.Windows.Toolkit.rd.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - diff --git a/UnitTests/UnitTests.UWP/Helpers/Test_StorageHelper.cs b/UnitTests/UnitTests.UWP/Helpers/Test_StorageHelper.cs index 71e459be102..0099a77ff49 100644 --- a/UnitTests/UnitTests.UWP/Helpers/Test_StorageHelper.cs +++ b/UnitTests/UnitTests.UWP/Helpers/Test_StorageHelper.cs @@ -4,8 +4,8 @@ using Microsoft.Toolkit.Uwp.Helpers; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json; using System; +using System.Text.Json; using UnitTests.UI; namespace UnitTests.Helpers @@ -24,7 +24,7 @@ public void Test_StorageHelper_LegacyIntTest() int input = 42; // simulate previous version by generating json and manually inserting it as string - string jsonInput = JsonConvert.SerializeObject(input); + string jsonInput = JsonSerializer.Serialize(input); storageHelper.Save(key, jsonInput); @@ -43,7 +43,7 @@ public void Test_StorageHelper_LegacyDateTest() DateTime input = new DateTime(2017, 12, 25); // simulate previous version by generating json and manually inserting it as string - string jsonInput = JsonConvert.SerializeObject(input); + string jsonInput = JsonSerializer.Serialize(input); storageHelper.Save(key, jsonInput); @@ -62,7 +62,7 @@ public void Test_StorageHelper_LegacyPersonTest() Person input = new Person() { Name = "Joe Bloggs", Age = 42 }; // simulate previous version by generating json and manually inserting it as string - string jsonInput = JsonConvert.SerializeObject(input); + string jsonInput = JsonSerializer.Serialize(input); storageHelper.Save(key, jsonInput); diff --git a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj index 0b40d7f34d8..c4b252d01f0 100644 --- a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj +++ b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj @@ -125,6 +125,9 @@ 4.3.0 + + 4.7.2 + From 48b1f543355c370222e40d0a545626d7dc07e9d2 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Fri, 7 Aug 2020 17:25:01 -0700 Subject: [PATCH 02/10] Updated InfiniteCanvas to use new .Net JsonSerializer. --- ...initeCanvasVirtualDrawingSurface.Render.cs | 28 ++--- .../InfiniteCanvas/Drawables/IDrawable.cs | 7 ++ .../InfiniteCanvas/Drawables/InkDrawable.cs | 35 ++++-- .../InfiniteCanvas/Drawables/TextDrawable.cs | 42 ++++++++ .../JsonConverters/IDrawableConverter.cs | 100 ++++++++++++++++++ .../JsonConverters/Matrix3x2Converter.cs | 76 +++++++++++++ .../JsonConverters/SerializableStroke.cs | 18 ++-- .../SerializableStrokeConverter.cs | 31 ++++++ .../Microsoft.Toolkit.Uwp.UI.Controls.csproj | 1 + 9 files changed, 307 insertions(+), 31 deletions(-) create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs create mode 100644 Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStrokeConverter.cs diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs index da628f5e6ef..9f7d238a1f7 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs @@ -78,11 +78,21 @@ internal void ClearAll(Rect viewPort) internal string GetSerializedList() { var exportModel = new InkCanvasExportModel { DrawableList = _drawableList, Version = 1 }; - return JsonSerializer.Serialize(exportModel, new JsonSerializerOptions + return JsonSerializer.Serialize(exportModel, GetJsonSerializerOptions()); + } + + private JsonSerializerOptions GetJsonSerializerOptions() + { + var jsonSerializerOptions = new JsonSerializerOptions { - // TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto - WriteIndented = true, - }); + WriteIndented = true + }; + + // This will be needed until These two issues are fixed: + // https://github.com/dotnet/runtime/issues/30083 + // https://github.com/dotnet/runtime/issues/29937 + jsonSerializerOptions.Converters.Add(new IDrawableConverter()); + return jsonSerializerOptions; } internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom) @@ -97,17 +107,11 @@ internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom) if (token.RootElement.ValueKind == JsonValueKind.Array) { // first sin, because of creating a file without versioning so we have to be able to import without breaking changes. - newList = JsonSerializer.Deserialize>(json, new JsonSerializerOptions - { - // TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto - }); + newList = JsonSerializer.Deserialize>(json, GetJsonSerializerOptions()); } else { - newList = JsonSerializer.Deserialize(json, new JsonSerializerOptions - { - // TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto - }).DrawableList; + newList = JsonSerializer.Deserialize(json, GetJsonSerializerOptions()).DrawableList; } foreach (var drawable in newList) diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/IDrawable.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/IDrawable.cs index ed9cc2756ea..a20aa9ec18c 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/IDrawable.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/IDrawable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Text.Json; using Microsoft.Graphics.Canvas; using Windows.Foundation; @@ -13,6 +14,12 @@ internal interface IDrawable bool IsVisible(Rect viewPort); + void WriteJson(Utf8JsonWriter writer); + + void ReadProperty(string propertyName, ref Utf8JsonReader reader); + + void OnDeserialized(); + bool IsActive { get; set; } Rect Bounds { get; set; } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs index e739e3591bf..3dac970475e 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.Serialization; +using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.Graphics.Canvas; using Windows.Foundation; @@ -19,6 +19,9 @@ internal class InkDrawable : IDrawable [JsonIgnore] public IReadOnlyList Strokes { get; set; } + [JsonPropertyName("$type")] + public string Type => IDrawableConverter.GetDiscriminator(GetType()); + public List SerializableStrokeList { get; set; } public Rect Bounds { get; set; } @@ -27,6 +30,10 @@ internal class InkDrawable : IDrawable internal static readonly InkStrokeBuilder StrokeBuilder = new InkStrokeBuilder(); + public InkDrawable() + { + } + public InkDrawable(IReadOnlyList strokes) { if (strokes == null || !strokes.Any()) @@ -83,8 +90,7 @@ private static InkPoint MapPointToToSessionBounds(InkPoint point, Rect sessionBo return new InkPoint(new Point(point.Position.X - sessionBounds.X, point.Position.Y - sessionBounds.Y), point.Pressure, point.TiltX, point.TiltY, point.Timestamp); } - [OnSerializing] - internal void OnSerializingMethod(StreamingContext context) + public void WriteJson(Utf8JsonWriter writer) { SerializableStrokeList = new List(Strokes.Count); foreach (var stroke in Strokes) @@ -103,10 +109,15 @@ internal void OnSerializingMethod(StreamingContext context) serializableStroke.PointTransform = stroke.PointTransform; SerializableStrokeList.Add(serializableStroke); } + + var options = new JsonSerializerOptions(); + options.Converters.Add(new SerializableStrokeConverter()); + JsonSerializer.Serialize(writer, this, options); + + SerializableStrokeList = null; } - [OnDeserialized] - internal void OnDeserializedMethod(StreamingContext context) + public void OnDeserialized() { var finalStrokeList = new List(SerializableStrokeList.Count); @@ -121,10 +132,18 @@ internal void OnDeserializedMethod(StreamingContext context) SerializableStrokeList = null; } - [OnSerialized] - internal void OnSerializedMethod(StreamingContext context) + public void ReadProperty(string propertyName, ref Utf8JsonReader reader) { - SerializableStrokeList = null; + switch (propertyName) + { + case "SerializableStrokeList": + var options = new JsonSerializerOptions(); + options.Converters.Add(new SerializableStrokeConverter()); + SerializableStrokeList = JsonSerializer.Deserialize>(ref reader, options); + break; + default: + break; + } } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs index fbb2450e2ee..24dbbf4fee3 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Graphics.Canvas; using Microsoft.Graphics.Canvas.Text; using Windows.Foundation; @@ -13,6 +15,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls { internal class TextDrawable : IDrawable { + [JsonPropertyName("$type")] + public string Type => IDrawableConverter.GetDiscriminator(GetType()); + public string Text { get; set; } public Rect Bounds { get; set; } @@ -27,6 +32,10 @@ internal class TextDrawable : IDrawable public bool IsItalic { get; set; } + public TextDrawable() + { + } + public TextDrawable(double left, double top, double width, double height, float fontSize, string text, Color textColor, bool isBold, bool isItalic) { Bounds = new Rect(left, top, width, height); @@ -76,5 +85,38 @@ public float HorizontalMarginBasedOnFont return ((100 - FontSize) / 10) + 5; } } + + public void WriteJson(Utf8JsonWriter writer) + { + JsonSerializer.Serialize(writer, this); + } + + public void OnDeserialized() + { + } + + public void ReadProperty(string propertyName, ref Utf8JsonReader reader) + { + switch (propertyName) + { + case "Text": + Text = reader.GetString(); + break; + case "FontSize": + FontSize = reader.GetSingle(); + break; + case "TextColor": + TextColor = JsonSerializer.Deserialize(ref reader); + break; + case "IsBold": + IsBold = reader.GetBoolean(); + break; + case "IsItalic": + IsItalic = reader.GetBoolean(); + break; + default: + break; + } + } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs new file mode 100644 index 00000000000..911f3fb6c77 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs @@ -0,0 +1,100 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Windows.Foundation; + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + internal class IDrawableConverter : JsonConverter + { + public IDrawableConverter() + { + } + + public override bool CanConvert(Type typeToConvert) => typeof(IDrawable).IsAssignableFrom(typeToConvert); + + public override IDrawable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + { + throw new JsonException(); + } + + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName) + { + throw new JsonException(); + } + + string propertyName = reader.GetString(); + if (propertyName != "$type") + { + throw new JsonException(); + } + + reader.Read(); + if (reader.TokenType != JsonTokenType.String) + { + throw new JsonException(); + } + + var typeDiscriminator = reader.GetString(); + IDrawable drawable; + if (typeDiscriminator == GetDiscriminator(typeof(InkDrawable))) + { + drawable = new InkDrawable(); + } + else if (typeDiscriminator == GetDiscriminator(typeof(TextDrawable))) + { + drawable = new TextDrawable(); + } + else + { + throw new JsonException(); + } + + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + { + drawable.OnDeserialized(); + return drawable; + } + + if (reader.TokenType == JsonTokenType.PropertyName) + { + propertyName = reader.GetString(); + reader.Read(); + switch (propertyName) + { + case "IsActive": + drawable.IsActive = reader.GetBoolean(); + break; + case "Bounds": + drawable.Bounds = JsonSerializer.Deserialize(ref reader); + break; + default: + drawable.ReadProperty(propertyName, ref reader); + break; + } + } + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, IDrawable drawable, JsonSerializerOptions options) + { + drawable.WriteJson(writer); + } + + internal static string GetDiscriminator(Type type) + { + return $"{type.FullName}, {type.Assembly.GetName().Name}"; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs new file mode 100644 index 00000000000..c74e26889bb --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Numerics; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + internal class Matrix3x2Converter : JsonConverter + { + public override Matrix3x2 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + { + throw new JsonException(); + } + + string propertyName; + Matrix3x2 matrix = default; + + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + { + return matrix; + } + + if (reader.TokenType == JsonTokenType.PropertyName) + { + propertyName = reader.GetString(); + reader.Read(); + switch (propertyName) + { + case "M11": + matrix.M11 = reader.GetSingle(); + break; + case "M12": + matrix.M12 = reader.GetSingle(); + break; + case "M21": + matrix.M21 = reader.GetSingle(); + break; + case "M22": + matrix.M22 = reader.GetSingle(); + break; + case "M31": + matrix.M31 = reader.GetSingle(); + break; + case "M32": + matrix.M32 = reader.GetSingle(); + break; + } + } + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, Matrix3x2 value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + + writer.WriteNumber("M11", value.M11); + writer.WriteNumber("M12", value.M12); + writer.WriteNumber("M21", value.M21); + writer.WriteNumber("M22", value.M22); + writer.WriteNumber("M31", value.M31); + writer.WriteNumber("M32", value.M32); + + writer.WriteEndObject(); + } + } +} diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs index da5a62f68e6..e6869730c39 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStroke.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Numerics; -using System.Runtime.Serialization; +using System.Text.Json; using System.Text.Json.Serialization; using Windows.UI.Input.Inking; @@ -29,8 +29,7 @@ internal class SerializableStroke public Matrix3x2 PointTransform { get; set; } - [OnSerializing] - internal void OnSerializingMethod(StreamingContext context) + internal void Write(Utf8JsonWriter writer, JsonSerializerOptions options) { SerializableFinalPointList = new List(FinalPointList.Count); foreach (var point in FinalPointList) @@ -60,10 +59,13 @@ internal void OnSerializingMethod(StreamingContext context) DrawAsHighlighter = DrawingAttributesIgnored.DrawAsHighlighter }; } + + JsonSerializer.Serialize(writer, this, options); + + SerializableFinalPointList = null; } - [OnDeserialized] - internal void OnDeserializedMethod(StreamingContext context) + internal void OnDeserialized() { var finalPointList = new List(SerializableFinalPointList.Count); @@ -108,11 +110,5 @@ internal void OnDeserializedMethod(StreamingContext context) SerializableFinalPointList = null; SerializableDrawingAttributesKind = null; } - - [OnSerialized] - internal void OnSerializedMethod(StreamingContext context) - { - SerializableFinalPointList = null; - } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStrokeConverter.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStrokeConverter.cs new file mode 100644 index 00000000000..186c7390c3b --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/SerializableStrokeConverter.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + internal class SerializableStrokeConverter : JsonConverter + { + public override SerializableStroke Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var matrixOptions = new JsonSerializerOptions(); + matrixOptions.Converters.Add(new Matrix3x2Converter()); + SerializableStroke serializableStroke = JsonSerializer.Deserialize(ref reader, matrixOptions); + + serializableStroke.OnDeserialized(); + + return serializableStroke; + } + + public override void Write(Utf8JsonWriter writer, SerializableStroke value, JsonSerializerOptions options) + { + var matrixOptions = new JsonSerializerOptions(); + matrixOptions.Converters.Add(new Matrix3x2Converter()); + value.Write(writer, matrixOptions); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj b/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj index 0785dd2fd3d..676f3004803 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Microsoft.Toolkit.Uwp.UI.Controls.csproj @@ -43,6 +43,7 @@ UWP Toolkit Windows Controls XAML Range WrapPanel Adaptive Markdown BladeView Blade CameraPreview Camera Carousel DockPanel DropShadow Expander GridSplitter HeaderedContent ImageEx InAppNotification InfiniteCanvas Master Details MasterDetails Orbit Radial Gauge RadiaGauge RadialProgressBar Scroll ScrollHeader StaggeredPanel Staggered Tile Tokenizing TextBox UniformGrid Uniform Grid false + 8.0 From b446d061d41af841ec918190553a3fc46c226022 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Thu, 13 Aug 2020 12:05:18 -0700 Subject: [PATCH 03/10] Simplified many using statements by changing the lang version to C#8 in the services project. --- .../Microsoft.Toolkit.Services.csproj | 1 + .../Services/LinkedIn/LinkedInDataProvider.cs | 65 +++---- .../MicrosoftTranslator/AzureAuthToken.cs | 26 ++- .../MicrosoftTranslator/TranslatorService.cs | 53 +++--- .../Services/Twitter/TwitterDataProvider.cs | 26 ++- .../Services/Twitter/TwitterOAuthRequest.cs | 108 +++++------ .../Services/Weibo/WeiboOAuthRequest.cs | 169 ++++++++---------- 7 files changed, 188 insertions(+), 260 deletions(-) diff --git a/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj b/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj index a7d3225ee7e..eda0b41f4ee 100644 --- a/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj +++ b/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj @@ -11,6 +11,7 @@ UWP Community Toolkit Windows Microsoft Graph OneDrive Twitter Translator LinkedIn service login OAuth + 8.0 CS8002;CS0618 false diff --git a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs index cf07a1c305e..2018e7cd33d 100644 --- a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs +++ b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs @@ -198,22 +198,18 @@ public async Task> GetDataAsync(LinkedInDataConfig var url = $"{_baseUrl}{config.Query}/~:({fields})?oauth2_access_token={Tokens.AccessToken}&format=json&count={maxRecords}&start={startRecord}"; - using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(url))) - { - request.Headers.Connection.TryParseAdd("Keep-Alive"); - - using (var response = await client.SendAsync(request).ConfigureAwait(false)) - { - var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(url)); + request.Headers.Connection.TryParseAdd("Keep-Alive"); - if (response.IsSuccessStatusCode && !string.IsNullOrEmpty(data)) - { - return parser.Parse(data); - } + using var response = await client.SendAsync(request).ConfigureAwait(false); + var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new RequestFailedException((System.Net.HttpStatusCode)response.StatusCode, data); - } + if (response.IsSuccessStatusCode && !string.IsNullOrEmpty(data)) + { + return parser.Parse(data); } + + throw new RequestFailedException((System.Net.HttpStatusCode)response.StatusCode, data); } /// @@ -234,22 +230,18 @@ public async Task ShareDataAsync(T dataToShare) var url = $"{_baseUrl}/people/~/shares?oauth2_access_token={Tokens.AccessToken}&format=json"; - using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(url))) - { - request.Headers.Add("x-li-format", "json"); - var stringContent = requestParser.Parse(shareRequest); - request.Content = new StringContent(stringContent, Encoding.UTF8, "application/json"); + using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(url)); + request.Headers.Add("x-li-format", "json"); + var stringContent = requestParser.Parse(shareRequest); + request.Content = new StringContent(stringContent, Encoding.UTF8, "application/json"); - using (var response = await client.SendAsync(request).ConfigureAwait(false)) - { - var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + using var response = await client.SendAsync(request).ConfigureAwait(false); + var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var responseParser = new LinkedInParser(); + var responseParser = new LinkedInParser(); - var listResults = responseParser.Parse(data) as List; - return listResults[0]; - } - } + var listResults = responseParser.Parse(data) as List; + return listResults[0]; } return default(U); @@ -275,20 +267,13 @@ private async Task GetAccessTokenAsync(LinkedInOAuthTokens tokens, strin + "&client_id=" + tokens.ClientId + "&client_secret=" + tokens.ClientSecret; - using (var request = new HttpRequestMessage(HttpMethod.Post, new Uri(url))) - { - using (var response = await client.SendAsync(request).ConfigureAwait(false)) - { - using (var jsonStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - { - using (var jsonDoc = await JsonDocument.ParseAsync(jsonStream).ConfigureAwait(false)) - { - var value = jsonDoc.RootElement.GetProperty("access_token"); - return value.GetString(); - } - } - } - } + using var request = new HttpRequestMessage(HttpMethod.Post, new Uri(url)); + using var response = await client.SendAsync(request).ConfigureAwait(false); + using var jsonStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + using var jsonDoc = await JsonDocument.ParseAsync(jsonStream).ConfigureAwait(false); + + var value = jsonDoc.RootElement.GetProperty("access_token"); + return value.GetString(); } private async Task GetAuthorizeCodeAsync(LinkedInOAuthTokens tokens, LinkedInPermissions permissions) diff --git a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs index 32dff4c0c74..a2607423256 100644 --- a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs +++ b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/AzureAuthToken.cs @@ -93,24 +93,22 @@ public async Task GetAccessTokenAsync() return _storedTokenValue; } - using (var request = new HttpRequestMessage(HttpMethod.Post, ServiceUrl)) - { - request.Headers.Add(OcpApimSubscriptionKeyHeader, SubscriptionKey); + using var request = new HttpRequestMessage(HttpMethod.Post, ServiceUrl); + request.Headers.Add(OcpApimSubscriptionKeyHeader, SubscriptionKey); - var response = await client.SendAsync(request).ConfigureAwait(false); - var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var response = await client.SendAsync(request).ConfigureAwait(false); + var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - if (!response.IsSuccessStatusCode) - { - var error = JsonSerializer.Deserialize(content); - throw new TranslatorServiceException(error?.Error?.Message); - } + if (!response.IsSuccessStatusCode) + { + var error = JsonSerializer.Deserialize(content); + throw new TranslatorServiceException(error?.Error?.Message); + } - _storedTokenTime = DateTime.Now; - _storedTokenValue = $"Bearer {content}"; + _storedTokenTime = DateTime.Now; + _storedTokenValue = $"Bearer {content}"; - return _storedTokenValue; - } + return _storedTokenValue; } } } diff --git a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs index 83c9a008956..aec1fb5841e 100644 --- a/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs +++ b/Microsoft.Toolkit.Services/Services/MicrosoftTranslator/TranslatorService.cs @@ -107,14 +107,13 @@ public async Task> DetectLanguagesWithResp await CheckUpdateTokenAsync().ConfigureAwait(false); var uriString = $"{BaseUrl}detect?{ApiVersion}"; - using (var request = CreateHttpRequest(uriString, HttpMethod.Post, input.Select(t => new { Text = t.Substring(0, Math.Min(t.Length, _MaxTextLengthForDetection)) }))) - { - var response = await client.SendAsync(request).ConfigureAwait(false); - var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + using var request = CreateHttpRequest(uriString, HttpMethod.Post, input.Select(t => new { Text = t.Substring(0, Math.Min(t.Length, _MaxTextLengthForDetection)) })); - var responseContent = JsonSerializer.Deserialize>(content); - return responseContent; - } + var response = await client.SendAsync(request).ConfigureAwait(false); + var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + + var responseContent = JsonSerializer.Deserialize>(content); + return responseContent; } /// @@ -131,24 +130,23 @@ public async Task> GetLanguageNamesAsync(string lan await CheckUpdateTokenAsync().ConfigureAwait(false); var uriString = $"{BaseUrl}languages?scope=translation&{ApiVersion}"; - using (var request = CreateHttpRequest(uriString)) + using var request = CreateHttpRequest(uriString); + + language = language ?? Language; + if (!string.IsNullOrWhiteSpace(language)) { - language = language ?? Language; - if (!string.IsNullOrWhiteSpace(language)) - { - // If necessary, adds the Accept-Language header in order to get localized language names. - request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(language)); - } + // If necessary, adds the Accept-Language header in order to get localized language names. + request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(language)); + } - var response = await client.SendAsync(request).ConfigureAwait(false); - var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var response = await client.SendAsync(request).ConfigureAwait(false); + var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var jsonContent = JsonDocument.Parse(content).RootElement.GetProperty("translation"); - var responseContent = JsonSerializer.Deserialize>(jsonContent.ToString()).ToList(); - responseContent.ForEach(r => r.Value.Code = r.Key); + var jsonContent = JsonDocument.Parse(content).RootElement.GetProperty("translation"); + var responseContent = JsonSerializer.Deserialize>(jsonContent.ToString()).ToList(); + responseContent.ForEach(r => r.Value.Code = r.Key); - return responseContent.Select(r => r.Value).OrderBy(r => r.Name).ToList(); - } + return responseContent.Select(r => r.Value).OrderBy(r => r.Name).ToList(); } /// @@ -215,14 +213,13 @@ public async Task> TranslateWithResponseAsync(I var toQueryString = string.Join("&", to.Select(t => $"to={t}")); var uriString = (string.IsNullOrWhiteSpace(from) ? $"{BaseUrl}translate?{toQueryString}" : $"{BaseUrl}translate?from={from}&{toQueryString}") + $"&{ApiVersion}"; - using (var request = CreateHttpRequest(uriString, HttpMethod.Post, input.Select(t => new { Text = t }))) - { - var response = await client.SendAsync(request).ConfigureAwait(false); - var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + using var request = CreateHttpRequest(uriString, HttpMethod.Post, input.Select(t => new { Text = t })); - var responseContent = JsonSerializer.Deserialize>(content); - return responseContent; - } + var response = await client.SendAsync(request).ConfigureAwait(false); + var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + + var responseContent = JsonSerializer.Deserialize>(content); + return responseContent; } /// diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs index b594fcba563..f4498ef5b8f 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterDataProvider.cs @@ -592,18 +592,16 @@ private async Task InitializeRequestAccessTokensAsync(string twitterCallba using (var request = new HttpRequestMessage(HttpMethod.Get, new Uri(twitterUrl))) { - using (var response = await _client.SendAsync(request).ConfigureAwait(false)) + using var response = await _client.SendAsync(request).ConfigureAwait(false); + var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + if (response.IsSuccessStatusCode) { - var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - if (response.IsSuccessStatusCode) - { - getResponse = data; - } - else - { - Debug.WriteLine("HttpHelper call failed trying to retrieve Twitter Request Tokens. Message: {0}", data); - return false; - } + getResponse = data; + } + else + { + Debug.WriteLine("HttpHelper call failed trying to retrieve Twitter Request Tokens. Message: {0}", data); + return false; } } @@ -676,10 +674,8 @@ private async Task ExchangeRequestTokenForAccessTokenAsync(string webAuthR { request.Headers.Authorization = new AuthenticationHeaderValue("OAuth", authorizationHeaderParams); - using (var response = await _client.SendAsync(request).ConfigureAwait(false)) - { - data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - } + using var response = await _client.SendAsync(request).ConfigureAwait(false); + data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } var screenName = ExtractTokenFromResponse(data, TwitterOAuthTokenType.ScreenName); diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs index 7ad7f835c50..303cee3de28 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterOAuthRequest.cs @@ -45,18 +45,14 @@ public TwitterOAuthRequest() /// String result. public async Task ExecuteGetAsync(Uri requestUri, TwitterOAuthTokens tokens, ISignatureManager signatureManager) { - using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri)) - { - var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager, "GET"); + using var request = new HttpRequestMessage(HttpMethod.Get, requestUri); + var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager, "GET"); - request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); + request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); - using (var response = await client.SendAsync(request).ConfigureAwait(false)) - { - response.ThrowIfNotValid(); - return ProcessErrors(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); - } - } + using var response = await client.SendAsync(request).ConfigureAwait(false); + response.ThrowIfNotValid(); + return ProcessErrors(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); } /// @@ -69,30 +65,22 @@ public async Task ExecuteGetAsync(Uri requestUri, TwitterOAuthTokens tok /// awaitable task public async Task ExecuteGetStreamAsync(Uri requestUri, TwitterOAuthTokens tokens, TwitterStreamCallbacks.RawJsonCallback callback, ISignatureManager signatureManager) { - using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri)) - { - var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager); + using var request = new HttpRequestMessage(HttpMethod.Get, requestUri); + var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager); - request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); + request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); + + using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + response.ThrowIfNotValid(); + using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + using var reader = new StreamReader(responseStream); + while (!_abort && !reader.EndOfStream) + { + var result = reader.ReadLine(); - using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) + if (!string.IsNullOrEmpty(result)) { - response.ThrowIfNotValid(); - using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - { - using (var reader = new StreamReader(responseStream)) - { - while (!_abort && !reader.EndOfStream) - { - var result = reader.ReadLine(); - - if (!string.IsNullOrEmpty(result)) - { - callback?.Invoke(result); - } - } - } - } + callback?.Invoke(result); } } } @@ -114,18 +102,14 @@ public void Abort() /// String result. public async Task ExecutePostAsync(Uri requestUri, TwitterOAuthTokens tokens, ISignatureManager signatureManager) { - using (var request = new HttpRequestMessage(HttpMethod.Post, requestUri)) - { - var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager, "POST"); + using var request = new HttpRequestMessage(HttpMethod.Post, requestUri); + var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager, "POST"); - request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); + request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); - using (var response = await client.SendAsync(request).ConfigureAwait(false)) - { - response.ThrowIfNotValid(); - return ProcessErrors(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); - } - } + using var response = await client.SendAsync(request).ConfigureAwait(false); + response.ThrowIfNotValid(); + return ProcessErrors(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); } /// @@ -143,32 +127,22 @@ public async Task ExecutePostMultipartAsync(Uri requestUri, TwitterOAuth try { - using (var multipartFormDataContent = new MultipartFormDataContent(boundary)) - { - using (var byteContent = new ByteArrayContent(content)) - { - multipartFormDataContent.Add(byteContent, "media"); - - using (var request = new HttpRequestMessage(HttpMethod.Post, requestUri)) - { - var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager, "POST"); - - request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); - - request.Content = multipartFormDataContent; - - using (var response = await client.SendAsync(request).ConfigureAwait(false)) - { - response.ThrowIfNotValid(); - using (var jsonResult = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - { - var jObj = await JsonDocument.ParseAsync(jsonResult).ConfigureAwait(false); - mediaId = jObj.RootElement.GetProperty("media_id_string"); - } - } - } - } - } + using var multipartFormDataContent = new MultipartFormDataContent(boundary); + using var byteContent = new ByteArrayContent(content); + multipartFormDataContent.Add(byteContent, "media"); + + using var request = new HttpRequestMessage(HttpMethod.Post, requestUri); + var requestBuilder = new TwitterOAuthRequestBuilder(requestUri, tokens, signatureManager, "POST"); + + request.Headers.Authorization = AuthenticationHeaderValue.Parse(requestBuilder.AuthorizationHeader); + + request.Content = multipartFormDataContent; + + using var response = await client.SendAsync(request).ConfigureAwait(false); + response.ThrowIfNotValid(); + using var jsonResult = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + var jObj = await JsonDocument.ParseAsync(jsonResult).ConfigureAwait(false); + mediaId = jObj.RootElement.GetProperty("media_id_string"); } catch (ObjectDisposedException) { diff --git a/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs b/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs index 011c9d8bc44..8db8a768507 100644 --- a/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs +++ b/Microsoft.Toolkit.Services/Services/Weibo/WeiboOAuthRequest.cs @@ -41,26 +41,22 @@ public WeiboOAuthRequest() /// String result. public async Task ExecuteGetAsync(Uri requestUri, WeiboOAuthTokens tokens) { - using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri)) + using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri); + UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri); + if (requestUriBuilder.Query.StartsWith("?")) { - UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri); - if (requestUriBuilder.Query.StartsWith("?")) - { - requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); - } - else - { - requestUriBuilder.Query = requestUriBuilder.Query + "?access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); - } + requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); + } + else + { + requestUriBuilder.Query = requestUriBuilder.Query + "?access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); + } - request.RequestUri = requestUriBuilder.Uri; + request.RequestUri = requestUriBuilder.Uri; - using (HttpResponseMessage response = await _client.SendAsync(request).ConfigureAwait(false)) - { - response.ThrowIfNotValid(); - return ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); - } - } + using HttpResponseMessage response = await _client.SendAsync(request).ConfigureAwait(false); + response.ThrowIfNotValid(); + return ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); } /// @@ -75,41 +71,33 @@ public async Task ExecutePostAsync(Uri requestUri, WeiboOAuthTokens var contentDict = new Dictionary(); contentDict.Add("status", status); - using (var formUrlEncodedContent = new FormUrlEncodedContent(contentDict)) + using var formUrlEncodedContent = new FormUrlEncodedContent(contentDict); + using var request = new HttpRequestMessage(HttpMethod.Post, requestUri); + UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri); + if (requestUriBuilder.Query.StartsWith("?")) { - using (var request = new HttpRequestMessage(HttpMethod.Post, requestUri)) - { - UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri); - if (requestUriBuilder.Query.StartsWith("?")) - { - requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); - } - else - { - requestUriBuilder.Query = requestUriBuilder.Query + "access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); - } - - request.RequestUri = requestUriBuilder.Uri; - - request.Content = formUrlEncodedContent; - - using (var response = await _client.SendAsync(request).ConfigureAwait(false)) - { - if (response.StatusCode == HttpStatusCode.OK) - { - using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - { - return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); - } - } - else - { - response.ThrowIfNotValid(); - ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); - return null; - } - } - } + requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); + } + else + { + requestUriBuilder.Query = requestUriBuilder.Query + "access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); + } + + request.RequestUri = requestUriBuilder.Uri; + + request.Content = formUrlEncodedContent; + + using var response = await _client.SendAsync(request).ConfigureAwait(false); + if (response.StatusCode == HttpStatusCode.OK) + { + using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); + } + else + { + response.ThrowIfNotValid(); + ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); + return null; } } @@ -125,52 +113,41 @@ public async Task ExecutePostMultipartAsync(Uri requestUri, WeiboOA { try { - using (var multipartFormDataContent = new MultipartFormDataContent()) + using var multipartFormDataContent = new MultipartFormDataContent(); + using var stringContent = new StringContent(status); + multipartFormDataContent.Add(stringContent, "status"); + using var byteContent = new ByteArrayContent(content); + + // Somehow Weibo's backend requires a Filename field to work + byteContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { FileName = "attachment", Name = "pic" }; + multipartFormDataContent.Add(byteContent, "pic"); + + using var request = new HttpRequestMessage(HttpMethod.Post, requestUri); + UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri); + if (requestUriBuilder.Query.StartsWith("?")) + { + requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); + } + else { - using (var stringContent = new StringContent(status)) - { - multipartFormDataContent.Add(stringContent, "status"); - using (var byteContent = new ByteArrayContent(content)) - { - // Somehow Weibo's backend requires a Filename field to work - byteContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { FileName = "attachment", Name = "pic" }; - multipartFormDataContent.Add(byteContent, "pic"); - - using (var request = new HttpRequestMessage(HttpMethod.Post, requestUri)) - { - UriBuilder requestUriBuilder = new UriBuilder(request.RequestUri); - if (requestUriBuilder.Query.StartsWith("?")) - { - requestUriBuilder.Query = requestUriBuilder.Query.Substring(1) + "&access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); - } - else - { - requestUriBuilder.Query = requestUriBuilder.Query + "access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); - } - - request.RequestUri = requestUriBuilder.Uri; - - request.Content = multipartFormDataContent; - - using (var response = await _client.SendAsync(request).ConfigureAwait(false)) - { - if (response.StatusCode == HttpStatusCode.OK) - { - using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - { - return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); - } - } - else - { - response.ThrowIfNotValid(); - ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); - return null; - } - } - } - } - } + requestUriBuilder.Query = requestUriBuilder.Query + "access_token=" + OAuthEncoder.UrlEncode(tokens.AccessToken); + } + + request.RequestUri = requestUriBuilder.Uri; + + request.Content = multipartFormDataContent; + + using var response = await _client.SendAsync(request).ConfigureAwait(false); + if (response.StatusCode == HttpStatusCode.OK) + { + using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); + } + else + { + response.ThrowIfNotValid(); + ProcessError(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); + return null; } } catch (ObjectDisposedException) From 043edd61d3d4e9eac6174b113580c5f6a31c6e56 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Thu, 13 Aug 2020 12:05:37 -0700 Subject: [PATCH 04/10] Update Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs Co-authored-by: Sergio Pedri --- .../Services/Twitter/TwitterCoordinatesConverter.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs index 5a53501286a..16c15bf3d56 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs @@ -22,14 +22,7 @@ public override bool CanConvert(Type objectType) public TwitterCoordinatesConverter(JsonSerializerOptions options) { - if (options?.GetConverter(typeof(double)) is JsonConverter doubleConverter) - { - _doubleConverter = doubleConverter; - } - else - { - throw new InvalidOperationException(); - } + _doubleConverter = options?.GetConverter(typeof(double)) as JsonConverter ?? throw new InvalidOperationException(); } public override TwitterCoordinates Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -119,4 +112,4 @@ public override void Write(Utf8JsonWriter writer, TwitterCoordinates value, Json throw new NotImplementedException(); } } -} \ No newline at end of file +} From b5542c019a5c1c81d91552dba017ccc4a55aed65 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Thu, 13 Aug 2020 12:27:50 -0700 Subject: [PATCH 05/10] Applied PR feedback. --- .../Services/Twitter/TwitterCoordinatesConverter.cs | 6 +++--- .../InfiniteCanvas/Drawables/InkDrawable.cs | 1 + .../InfiniteCanvas/Drawables/TextDrawable.cs | 1 + .../InfiniteCanvas/JsonConverters/IDrawableConverter.cs | 4 ---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs b/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs index 16c15bf3d56..3e459a1cfee 100644 --- a/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs +++ b/Microsoft.Toolkit.Services/Services/Twitter/TwitterCoordinatesConverter.cs @@ -18,11 +18,11 @@ public override bool CanConvert(Type objectType) return false; } - private readonly JsonConverter _doubleConverter; + private readonly JsonConverter doubleConverter; public TwitterCoordinatesConverter(JsonSerializerOptions options) { - _doubleConverter = options?.GetConverter(typeof(double)) as JsonConverter ?? throw new InvalidOperationException(); + doubleConverter = options?.GetConverter(typeof(double)) as JsonConverter ?? throw new InvalidOperationException(); } public override TwitterCoordinates Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -104,7 +104,7 @@ public override TwitterCoordinates Read(ref Utf8JsonReader reader, Type typeToCo private double ReadProperty(ref Utf8JsonReader reader, JsonSerializerOptions options) { reader.Read(); - return _doubleConverter.Read(ref reader, typeof(double), options); + return doubleConverter.Read(ref reader, typeof(double), options); } public override void Write(Utf8JsonWriter writer, TwitterCoordinates value, JsonSerializerOptions options) diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs index 3dac970475e..9da83196804 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs @@ -30,6 +30,7 @@ internal class InkDrawable : IDrawable internal static readonly InkStrokeBuilder StrokeBuilder = new InkStrokeBuilder(); + // Don't remove! Used for deserialization. public InkDrawable() { } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs index 24dbbf4fee3..7f9604dc12a 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs @@ -32,6 +32,7 @@ internal class TextDrawable : IDrawable public bool IsItalic { get; set; } + // Don't remove! Used for deserialization. public TextDrawable() { } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs index 911f3fb6c77..19fdc0472b4 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/IDrawableConverter.cs @@ -11,10 +11,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls { internal class IDrawableConverter : JsonConverter { - public IDrawableConverter() - { - } - public override bool CanConvert(Type typeToConvert) => typeof(IDrawable).IsAssignableFrom(typeToConvert); public override IDrawable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) From df7dab1a449ccbb8df91cff8c2822c82dcd1a644 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Thu, 13 Aug 2020 15:05:01 -0700 Subject: [PATCH 06/10] Small improvement, removing magic number. --- .../Services/LinkedIn/LinkedInDataProvider.cs | 4 ++-- .../Services/LinkedIn/LinkedInPermissions.cs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs index 2018e7cd33d..4ebffa1c5f9 100644 --- a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs +++ b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs @@ -81,8 +81,8 @@ public LinkedInDataProvider(LinkedInOAuthTokens tokens, LinkedInPermissions requ throw new ArgumentException("Missing callback uri"); } - // Check if outside the bounds of the LinkedInPermissions Enum - if (requiredPermissions < 0 || requiredPermissions > (LinkedInPermissions)15) + // Check if its a valid combination of LinkedInPermissions + if ((~(int)LinkedInPermissionsHelpers.AllPermissions & (int)requiredPermissions) == 0) { throw new ArgumentException("Error retrieving required permissions"); } diff --git a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInPermissions.cs b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInPermissions.cs index 4042818c797..6d2d2fe756a 100644 --- a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInPermissions.cs +++ b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInPermissions.cs @@ -37,4 +37,18 @@ public enum LinkedInPermissions /// WriteShare = 8 } + +#pragma warning disable SA1649 // File name should match first type name + internal static class LinkedInPermissionsHelpers + { + /// + /// Internal AllPermissions for LinkedInPermissions, so we don't expose it. Keep it in sync with + /// + internal const LinkedInPermissions AllPermissions = + LinkedInPermissions.ReadBasicProfile | + LinkedInPermissions.ReadEmailAddress | + LinkedInPermissions.ReadWriteCompanyAdmin | + LinkedInPermissions.WriteShare; + } +#pragma warning restore SA1649 // File name should match first type name } From 00b7241d62470f9a31b92ab304bf6535d5d70ae8 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Thu, 13 Aug 2020 15:30:04 -0700 Subject: [PATCH 07/10] Update Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs Co-authored-by: Sergio Pedri --- .../Services/LinkedIn/LinkedInDataProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs index 4ebffa1c5f9..4847bc31077 100644 --- a/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs +++ b/Microsoft.Toolkit.Services/Services/LinkedIn/LinkedInDataProvider.cs @@ -82,7 +82,7 @@ public LinkedInDataProvider(LinkedInOAuthTokens tokens, LinkedInPermissions requ } // Check if its a valid combination of LinkedInPermissions - if ((~(int)LinkedInPermissionsHelpers.AllPermissions & (int)requiredPermissions) == 0) + if ((~(int)LinkedInPermissionsHelpers.AllPermissions & (int)requiredPermissions) != 0) { throw new ArgumentException("Error retrieving required permissions"); } From e8981027facbbdf4540f1925b599e2243cdc5454 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Tue, 18 Aug 2020 11:15:28 -0700 Subject: [PATCH 08/10] Remove extra blank line Co-authored-by: Sergio Pedri --- Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj b/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj index eda0b41f4ee..cbc40a855c6 100644 --- a/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj +++ b/Microsoft.Toolkit.Services/Microsoft.Toolkit.Services.csproj @@ -10,7 +10,6 @@ - Facebook: Album, DataConfig, DataHost, OAuthTokens, Permissions, Photo, Picture, PictureData, PlatformImageSource, Post, RequestSource, Service. UWP Community Toolkit Windows Microsoft Graph OneDrive Twitter Translator LinkedIn service login OAuth - 8.0 CS8002;CS0618 false @@ -54,4 +53,4 @@ - \ No newline at end of file + From 915fdc7e3b1a7fcd461e4bbdd924755016197216 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Tue, 15 Sep 2020 12:35:53 -0700 Subject: [PATCH 09/10] Fix infinite canvas json parsing regression. --- ...initeCanvasVirtualDrawingSurface.Render.cs | 21 ++-- .../JsonConverters/Matrix3x2Converter.cs | 7 ++ .../Assets/Samples/InfiniteCanvasExport.json | 102 ++++++++++++++++++ .../Test_InfiniteCanvas_Regression.cs | 43 ++++++++ UnitTests/UnitTests.UWP/UnitTests.UWP.csproj | 2 + 5 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 UnitTests/UnitTests.UWP/Assets/Samples/InfiniteCanvasExport.json create mode 100644 UnitTests/UnitTests.UWP/UI/Controls/Test_InfiniteCanvas_Regression.cs diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs index 269d7523312..bb9a7648252 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs @@ -81,7 +81,7 @@ internal string GetSerializedList() return JsonSerializer.Serialize(exportModel, GetJsonSerializerOptions()); } - private JsonSerializerOptions GetJsonSerializerOptions() + private static JsonSerializerOptions GetJsonSerializerOptions() { var jsonSerializerOptions = new JsonSerializerOptions { @@ -95,13 +95,8 @@ private JsonSerializerOptions GetJsonSerializerOptions() return jsonSerializerOptions; } - internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom) + internal static List LoadJson(string json) { - _visibleList.Clear(); - _drawableList.Clear(); - _undoCommands.Clear(); - _redoCommands.Clear(); - var token = JsonDocument.Parse(json); List newList; if (token.RootElement.ValueKind == JsonValueKind.Array) @@ -114,6 +109,18 @@ internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom) newList = JsonSerializer.Deserialize(json, GetJsonSerializerOptions()).DrawableList; } + return newList; + } + + internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom) + { + _visibleList.Clear(); + _drawableList.Clear(); + _undoCommands.Clear(); + _redoCommands.Clear(); + + var newList = LoadJson(json); + foreach (var drawable in newList) { _drawableList.Add(drawable); diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs index c74e26889bb..3fbbd9211d9 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/JsonConverters/Matrix3x2Converter.cs @@ -52,6 +52,13 @@ public override Matrix3x2 Read(ref Utf8JsonReader reader, Type typeToConvert, Js case "M32": matrix.M32 = reader.GetSingle(); break; + case "IsIdentity": + // Ignore, as it is readonly, and from v1 + break; + case "Translation": + var translation = JsonSerializer.Deserialize(ref reader); + matrix.Translation = translation; + break; } } } diff --git a/UnitTests/UnitTests.UWP/Assets/Samples/InfiniteCanvasExport.json b/UnitTests/UnitTests.UWP/Assets/Samples/InfiniteCanvasExport.json new file mode 100644 index 00000000000..08a856e87a9 --- /dev/null +++ b/UnitTests/UnitTests.UWP/Assets/Samples/InfiniteCanvasExport.json @@ -0,0 +1,102 @@ +{ + "DrawableList": [ + { + "$type": "Microsoft.Toolkit.Uwp.UI.Controls.InkDrawable, Microsoft.Toolkit.Uwp.UI.Controls", + "SerializableStrokeList": [ + { + "DrawingAttributes": { + "Color": { + "A": 255, + "R": 0, + "G": 0, + "B": 0 + }, + "FitToCurve": true, + "IgnorePressure": false, + "IgnoreTilt": true, + "Size": { + "Width": 4.0, + "Height": 4.0, + "IsEmpty": false + }, + "PenTip": 0, + "PenTipTransform": { + "M11": 1.0, + "M12": 0.0, + "M21": 0.0, + "M22": 1.0, + "M31": 0.0, + "M32": 0.0, + "IsIdentity": true, + "Translation": { + "X": 0.0, + "Y": 0.0 + } + }, + "DrawAsHighlighter": false + }, + "SerializableFinalPointList": [ + { + "Position": { + "X": 103.97531127929688, + "Y": 45.995269775390625 + }, + "Pressure": 0.5, + "TiltX": 0.0, + "TiltY": 0.0, + "Timestamp": 0 + }, + { + "Position": { + "X": 103.80825805664063, + "Y": 45.995269775390625 + }, + "Pressure": 0.5, + "TiltX": 0.0, + "TiltY": 0.0, + "Timestamp": 0 + }, + { + "Position": { + "X": 103.41259002685547, + "Y": 45.995269775390625 + }, + "Pressure": 0.5, + "TiltX": 0.0, + "TiltY": 0.0, + "Timestamp": 0 + } + ], + "SerializableDrawingAttributesKind": 0, + "SerializableDrawingAttributesPencilProperties": null, + "PointTransform": { + "M11": 1.0, + "M12": 0.0, + "M21": 0.0, + "M22": 1.0, + "M31": 0.0, + "M32": 0.0, + "IsIdentity": true, + "Translation": { + "X": 0.0, + "Y": 0.0 + } + } + } + ], + "Bounds": { + "X": 69.949455261230469, + "Y": 28.069997787475586, + "Width": 1668.2589111328125, + "Height": 280.38735961914062, + "Left": 69.949455261230469, + "Top": 28.069997787475586, + "Right": 1738.2083740234375, + "Bottom": 308.45736694335938, + "IsEmpty": false + }, + "IsActive": true + } + ], + "Version": 1 +} \ No newline at end of file diff --git a/UnitTests/UnitTests.UWP/UI/Controls/Test_InfiniteCanvas_Regression.cs b/UnitTests/UnitTests.UWP/UI/Controls/Test_InfiniteCanvas_Regression.cs new file mode 100644 index 00000000000..5c52be75339 --- /dev/null +++ b/UnitTests/UnitTests.UWP/UI/Controls/Test_InfiniteCanvas_Regression.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.Toolkit.Uwp.Helpers; +using Microsoft.Toolkit.Uwp.UI.Controls; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Windows.ApplicationModel.Core; +using Windows.UI.Core; + +namespace UnitTests.UI.Controls +{ + [TestClass] + public class Test_InfiniteCanvas_Regression + { + [TestCategory("InfiniteCanvas")] + [TestMethod] + public async Task Test_InfiniteCanvas_LoadsV1File() + { + var taskSource = new TaskCompletionSource(); + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( + CoreDispatcherPriority.Normal, async () => + { + try + { + string json = await StorageFileHelper.ReadTextFromPackagedFileAsync(@"Assets\Samples\InfiniteCanvasExport.json"); + + InfiniteCanvasVirtualDrawingSurface.LoadJson(json).Should().NotBeEmpty(); + + taskSource.SetResult(null); + } + catch (Exception e) + { + taskSource.SetException(e); + } + }); + await taskSource.Task; + } + } +} \ No newline at end of file diff --git a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj index 4f25839b00f..a9893fa92c0 100644 --- a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj +++ b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj @@ -180,6 +180,7 @@ + @@ -204,6 +205,7 @@ Designer + From 89dafd15cfedeaf58de6c27ea2342dc4bb3a1a6f Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Tue, 15 Sep 2020 17:03:42 -0700 Subject: [PATCH 10/10] Fixed .Net Native compilation of System.Text.Json. --- .../Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml b/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml index 890b5155e78..140de69eea9 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Properties/Microsoft.Toolkit.Uwp.UI.Controls.rd.xml @@ -2,5 +2,6 @@ +