From 8f0a4edbc0934223739d57bd69558dc762ed35ab Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 27 Oct 2023 14:38:39 -0400 Subject: [PATCH 01/11] - dotnet format Signed-off-by: Vincent Biret --- .../ApiClientBuilderTests.cs | 14 ++--- .../ApiKeyAuthenticationProviderTests.cs | 24 +++++--- .../Authentication/AuthenticationTests.cs | 12 ++-- .../Store/InMemoryBackingStoreTests.cs | 56 +++++++++---------- src/ApiClientBuilder.cs | 2 +- src/ApiException.cs | 6 +- src/BaseRequestBuilder.cs | 4 +- src/IResponseHandler.cs | 4 +- src/NativeResponseHandler.cs | 4 +- src/QueryParameterAttribute.cs | 4 +- .../ApiKeyAuthenticationProvider.cs | 20 ++++--- .../BaseBearerTokenAuthenticationProvider.cs | 2 +- src/extensions/IDictionaryExtensions.cs | 2 +- src/serialization/ParseNodeFactoryRegistry.cs | 2 +- src/serialization/ParseNodeHelper.cs | 10 ++-- .../SerializationWriterFactoryRegistry.cs | 2 +- src/store/InMemoryBackingStore.cs | 10 ++-- 17 files changed, 96 insertions(+), 82 deletions(-) diff --git a/Microsoft.Kiota.Abstractions.Tests/ApiClientBuilderTests.cs b/Microsoft.Kiota.Abstractions.Tests/ApiClientBuilderTests.cs index 7da19e0a..d377feb4 100644 --- a/Microsoft.Kiota.Abstractions.Tests/ApiClientBuilderTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/ApiClientBuilderTests.cs @@ -8,7 +8,7 @@ namespace Microsoft.Kiota.Abstractions.Tests public class ApiClientBuilderTests { private const string StreamContentType = "application/octet-stream"; - + [Fact] public void EnableBackingStoreForSerializationWriterFactory() { @@ -16,12 +16,12 @@ public void EnableBackingStoreForSerializationWriterFactory() var serializationFactoryRegistry = new SerializationWriterFactoryRegistry(); var mockSerializationWriterFactory = new Mock(); serializationFactoryRegistry.ContentTypeAssociatedFactories.TryAdd(StreamContentType, mockSerializationWriterFactory.Object); - + Assert.IsNotType(serializationFactoryRegistry.ContentTypeAssociatedFactories[StreamContentType]); - + // Act ApiClientBuilder.EnableBackingStoreForSerializationWriterFactory(serializationFactoryRegistry); - + // Assert the type has changed due to backing store enabling Assert.IsType(serializationFactoryRegistry.ContentTypeAssociatedFactories[StreamContentType]); } @@ -52,12 +52,12 @@ public void EnableBackingStoreForParseNodeFactory() var parseNodeRegistry = new ParseNodeFactoryRegistry(); var mockParseNodeFactory = new Mock(); parseNodeRegistry.ContentTypeAssociatedFactories.TryAdd(StreamContentType, mockParseNodeFactory.Object); - + Assert.IsNotType(parseNodeRegistry.ContentTypeAssociatedFactories[StreamContentType]); - + // Act ApiClientBuilder.EnableBackingStoreForParseNodeFactory(parseNodeRegistry); - + // Assert the type has changed due to backing store enabling Assert.IsType(parseNodeRegistry.ContentTypeAssociatedFactories[StreamContentType]); } diff --git a/Microsoft.Kiota.Abstractions.Tests/Authentication/ApiKeyAuthenticationProviderTests.cs b/Microsoft.Kiota.Abstractions.Tests/Authentication/ApiKeyAuthenticationProviderTests.cs index f9e236fe..8473a35a 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Authentication/ApiKeyAuthenticationProviderTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Authentication/ApiKeyAuthenticationProviderTests.cs @@ -5,9 +5,11 @@ namespace Microsoft.Kiota.Abstractions.Tests; -public class ApiKeyAuthenticationProviderTests { +public class ApiKeyAuthenticationProviderTests +{ [Fact] - public void DefensiveProgramming() { + public void DefensiveProgramming() + { Assert.Throws(() => new ApiKeyAuthenticationProvider(null, "param", ApiKeyAuthenticationProvider.KeyLocation.Header)); Assert.Throws(() => new ApiKeyAuthenticationProvider("key", null, ApiKeyAuthenticationProvider.KeyLocation.Header)); @@ -15,9 +17,11 @@ public void DefensiveProgramming() { Assert.ThrowsAsync(async () => await value.AuthenticateRequestAsync(null)); } [Fact] - public async Task AddsInHeader() { + public async Task AddsInHeader() + { var value = new ApiKeyAuthenticationProvider("key", "param", ApiKeyAuthenticationProvider.KeyLocation.Header); - var request = new RequestInformation { + var request = new RequestInformation + { UrlTemplate = "https://localhost{?param1}", }; await value.AuthenticateRequestAsync(request); @@ -25,9 +29,11 @@ public async Task AddsInHeader() { Assert.Contains("param", request.Headers.Keys); } [Fact] - public async Task AddsInQueryParameters() { + public async Task AddsInQueryParameters() + { var value = new ApiKeyAuthenticationProvider("key", "param", ApiKeyAuthenticationProvider.KeyLocation.QueryParameter); - var request = new RequestInformation { + var request = new RequestInformation + { UrlTemplate = "https://localhost{?param1}", }; await value.AuthenticateRequestAsync(request); @@ -35,9 +41,11 @@ public async Task AddsInQueryParameters() { Assert.DoesNotContain("param", request.Headers.Keys); } [Fact] - public async Task AddsInQueryParametersWithOtherParameters() { + public async Task AddsInQueryParametersWithOtherParameters() + { var value = new ApiKeyAuthenticationProvider("key", "param", ApiKeyAuthenticationProvider.KeyLocation.QueryParameter); - var request = new RequestInformation { + var request = new RequestInformation + { UrlTemplate = "https://localhost{?param1}", }; request.QueryParameters.Add("param1", "value1"); diff --git a/Microsoft.Kiota.Abstractions.Tests/Authentication/AuthenticationTests.cs b/Microsoft.Kiota.Abstractions.Tests/Authentication/AuthenticationTests.cs index e84021d8..78c0a567 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Authentication/AuthenticationTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Authentication/AuthenticationTests.cs @@ -55,16 +55,16 @@ public async Task BaseBearerTokenAuthenticationProviderSetsBearerHeader() } [Theory] - [InlineData("https://graph.microsoft.com",true)]// PASS - [InlineData("https://graph.microsoft.us/v1.0/me",true)]// PASS as we don't look at the path segment - [InlineData("https://test.microsoft.com",false)]// Fail - [InlineData("https://grAph.MicrosofT.com",true)] // PASS since we don't care about case - [InlineData("https://developer.microsoft.com",false)] // Failed + [InlineData("https://graph.microsoft.com", true)]// PASS + [InlineData("https://graph.microsoft.us/v1.0/me", true)]// PASS as we don't look at the path segment + [InlineData("https://test.microsoft.com", false)]// Fail + [InlineData("https://grAph.MicrosofT.com", true)] // PASS since we don't care about case + [InlineData("https://developer.microsoft.com", false)] // Failed public void AllowedHostValidatorValidatesUrls(string urlToTest, bool expectedResult) { // Test through the constructor // Arrange - var allowList = new[] { "graph.microsoft.com", "graph.microsoft.us"}; + var allowList = new[] { "graph.microsoft.com", "graph.microsoft.us" }; var validator = new AllowedHostsValidator(allowList); // Act diff --git a/Microsoft.Kiota.Abstractions.Tests/Store/InMemoryBackingStoreTests.cs b/Microsoft.Kiota.Abstractions.Tests/Store/InMemoryBackingStoreTests.cs index 7be78cdb..0758b56f 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Store/InMemoryBackingStoreTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Store/InMemoryBackingStoreTests.cs @@ -21,7 +21,7 @@ public void SetsAndGetsValueFromStore() testBackingStore.Set("name", "Peter"); // Assert Assert.NotEmpty(testBackingStore.Enumerate()); - Assert.Equal("Peter",testBackingStore.Enumerate().First().Value); + Assert.Equal("Peter", testBackingStore.Enumerate().First().Value); } [Fact] @@ -66,7 +66,7 @@ public void TestsBackingStoreEmbeddedInModel() }; testUser.BackingStore.InitializationCompleted = true; // Act on the data by making a change - testUser.BusinessPhones = new List + testUser.BusinessPhones = new List { "+1 234 567 891" }; @@ -84,7 +84,7 @@ public void TestsBackingStoreEmbeddedInModelWithAdditionDataValues() var testUser = new TestEntity { Id = "84c747c1-d2c0-410d-ba50-fc23e0b4abbe", - AdditionalData = new Dictionary + AdditionalData = new Dictionary { { "extensionData" , null } } @@ -182,7 +182,7 @@ public void TestsBackingStoreEmbeddedInModelWithCollectionPropertyModifiedByAdd( Assert.Equal("businessPhones", changedValues.First().Key); var businessPhones = testUser.BackingStore.Get>("businessPhones"); Assert.NotNull(businessPhones); - Assert.Equal(2,businessPhones.Count);//both items come back as the property is dirty + Assert.Equal(2, businessPhones.Count);//both items come back as the property is dirty } [Fact] public void TestsBackingStoreEmbeddedInModelWithBySettingNestedIBackedModel() @@ -194,7 +194,7 @@ public void TestsBackingStoreEmbeddedInModelWithBySettingNestedIBackedModel() }; testUser.BackingStore.InitializationCompleted = true; // Act on the data by making a change - testUser.Manager = new TestEntity + testUser.Manager = new TestEntity { Id = "2fe22fe5-1132-42cf-90f9-1dc17e325a74" }; @@ -206,7 +206,7 @@ public void TestsBackingStoreEmbeddedInModelWithBySettingNestedIBackedModel() Assert.Equal("manager", changedValues.First().Key); var manager = changedValues.First().Value as TestEntity; Assert.NotNull(manager); - Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74",manager.Id); + Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74", manager.Id); var testUserSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.BackingStore); Assert.Empty(testUserSubscriptions);// subscription only is added in nested store var managerSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.Manager.BackingStore); @@ -238,7 +238,7 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModel() Assert.Equal("manager", changedValues.First().Key);//Backingstore should detect manager property changed var manager = changedValues.First().Value as TestEntity; Assert.NotNull(manager); - Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74",manager.Id); + Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74", manager.Id); var testUserSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.BackingStore); Assert.Empty(testUserSubscriptions);// subscription only is added in nested store var managerSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.Manager.BackingStore); @@ -269,13 +269,13 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelRetu Assert.NotEmpty(changedValues); Assert.Single(changedValues); Assert.Equal("manager", changedValues.First().Key);//BackingStore should detect manager property changed - var changedNestedValues = testUser.Manager.BackingStore.Enumerate().ToDictionary(x => x.Key, y=> y.Value); - Assert.Equal(4,changedNestedValues.Count); + var changedNestedValues = testUser.Manager.BackingStore.Enumerate().ToDictionary(x => x.Key, y => y.Value); + Assert.Equal(4, changedNestedValues.Count); Assert.True(changedNestedValues.ContainsKey("id")); Assert.True(changedNestedValues.ContainsKey("businessPhones")); var manager = changedValues.First().Value as TestEntity; Assert.NotNull(manager); - Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74",manager.Id); + Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74", manager.Id); var testUserSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.BackingStore); Assert.Empty(testUserSubscriptions);// subscription only is added in nested store var managerSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.Manager.BackingStore); @@ -288,13 +288,13 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl var testUser = new TestEntity { Id = "84c747c1-d2c0-410d-ba50-fc23e0b4abbe", - Colleagues = new List + Colleagues = new List { new TestEntity { Id = "2fe22fe5-1132-42cf-90f9-1dc17e325a74" } - } + } }; testUser.BackingStore.InitializationCompleted = testUser.Colleagues[0].BackingStore.InitializationCompleted = true; // Act on the data by making a change in the nested Ibackedmodel collection item @@ -310,7 +310,7 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl Assert.Equal("colleagues", changedValues.First().Key);//Backingstore should detect manager property changed var colleagues = testUser.BackingStore.Get>("colleagues"); Assert.NotNull(colleagues); - Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74",colleagues[0].Id); + Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74", colleagues[0].Id); var testUserSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.BackingStore); Assert.Empty(testUserSubscriptions);// subscription only is added in nested store var colleagueSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.Colleagues[0].BackingStore); @@ -323,13 +323,13 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl var testUser = new TestEntity { Id = "84c747c1-d2c0-410d-ba50-fc23e0b4abbe", - Colleagues = new List + Colleagues = new List { new TestEntity { Id = "2fe22fe5-1132-42cf-90f9-1dc17e325a74" } - } + } }; testUser.BackingStore.InitializationCompleted = testUser.Colleagues[0].BackingStore.InitializationCompleted = true; // Act on the data by making a change in the nested Ibackedmodel collection item @@ -344,8 +344,8 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl Assert.NotEmpty(changedValues); Assert.Single(changedValues); Assert.Equal("colleagues", changedValues.First().Key);//BackingStore should detect manager property changed - var changedNestedValues = testUser.Colleagues[0].BackingStore.Enumerate().ToDictionary(x => x.Key, y=> y.Value); - Assert.Equal(4,changedNestedValues.Count); + var changedNestedValues = testUser.Colleagues[0].BackingStore.Enumerate().ToDictionary(x => x.Key, y => y.Value); + Assert.Equal(4, changedNestedValues.Count); Assert.True(changedNestedValues.ContainsKey("id")); Assert.True(changedNestedValues.ContainsKey("businessPhones")); var testUserSubscriptions = GetSubscriptionsPropertyFromBackingStore(testUser.BackingStore); @@ -360,7 +360,7 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl var testUser = new TestEntity { Id = "84c747c1-d2c0-410d-ba50-fc23e0b4abbe", - Colleagues = new List + Colleagues = new List { new TestEntity { @@ -370,7 +370,7 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl "+1 234 567 891" } } - } + } }; testUser.BackingStore.InitializationCompleted = testUser.Colleagues[0].BackingStore.InitializationCompleted = true; // Act on the data by making a change in the nested Ibackedmodel collection item @@ -382,8 +382,8 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl Assert.NotEmpty(changedValues); Assert.Single(changedValues); Assert.Equal("colleagues", changedValues.First().Key);//Backingstore should detect manager property changed - var changedNestedValues = testUser.Colleagues[0].BackingStore.Enumerate().ToDictionary(x => x.Key, y=> y.Value); - Assert.Equal(4,changedNestedValues.Count); + var changedNestedValues = testUser.Colleagues[0].BackingStore.Enumerate().ToDictionary(x => x.Key, y => y.Value); + Assert.Equal(4, changedNestedValues.Count); Assert.True(changedNestedValues.ContainsKey("id")); Assert.True(changedNestedValues.ContainsKey("businessPhones")); var businessPhones = ((Tuple)changedNestedValues["businessPhones"]).Item1; @@ -400,7 +400,7 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl var testUser = new TestEntity { Id = "84c747c1-d2c0-410d-ba50-fc23e0b4abbe", - Colleagues = new List + Colleagues = new List { new TestEntity { @@ -410,7 +410,7 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl "+1 234 567 891" } } - } + } }; testUser.BackingStore.InitializationCompleted = testUser.Colleagues[0].BackingStore.InitializationCompleted = true; // Act on the data by making a change in the nested Ibackedmodel collection item @@ -421,7 +421,7 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl // Assert by retrieving only changed values testUser.BackingStore.ReturnOnlyChangedValues = true; testUser.Colleagues[0].BackingStore.ReturnOnlyChangedValues = true; //serializer will do this. - var changedValues = testUser.BackingStore.Enumerate().ToDictionary(x => x.Key, y=> y.Value); + var changedValues = testUser.BackingStore.Enumerate().ToDictionary(x => x.Key, y => y.Value); Assert.NotEmpty(changedValues); Assert.Single(changedValues); Assert.Equal("colleagues", changedValues.First().Key);//Backingstore should detect manager property changed @@ -429,8 +429,8 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl Assert.Equal(2, colleagues.Count); Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74", colleagues[0].Id); Assert.Equal("2fe22fe5-1132-42cf-90f9-1dc17e325a74", colleagues[1].Id); - var changedNestedValues = testUser.Colleagues[0].BackingStore.Enumerate().ToDictionary(x => x.Key, y=> y.Value); - Assert.Equal(4,changedNestedValues.Count); + var changedNestedValues = testUser.Colleagues[0].BackingStore.Enumerate().ToDictionary(x => x.Key, y => y.Value); + Assert.Equal(4, changedNestedValues.Count); Assert.True(changedNestedValues.ContainsKey("id")); Assert.True(changedNestedValues.ContainsKey("businessPhones")); var businessPhones = ((Tuple)changedNestedValues["businessPhones"]).Item1; @@ -448,9 +448,9 @@ public void TestsBackingStoreEmbeddedInModelWithByUpdatingNestedIBackedModelColl /// private static IDictionary> GetSubscriptionsPropertyFromBackingStore(IBackingStore backingStore) { - if(backingStore is not InMemoryBackingStore inMemoryBackingStore) + if(backingStore is not InMemoryBackingStore inMemoryBackingStore) return default; - + var subscriptionsFieldInfo = typeof(InMemoryBackingStore).GetField("subscriptions", BindingFlags.NonPublic | BindingFlags.Instance); return (IDictionary>)subscriptionsFieldInfo?.GetValue(inMemoryBackingStore); } diff --git a/src/ApiClientBuilder.cs b/src/ApiClientBuilder.cs index 566280b0..f83b02f2 100644 --- a/src/ApiClientBuilder.cs +++ b/src/ApiClientBuilder.cs @@ -71,7 +71,7 @@ public static IParseNodeFactory EnableBackingStoreForParseNodeFactory(IParseNode } else result = new BackingStoreParseNodeFactory(original); - + return result; } private static void EnableBackingStoreForParseNodeRegistry(ParseNodeFactoryRegistry registry) diff --git a/src/ApiException.cs b/src/ApiException.cs index b464c5f2..334d1053 100644 --- a/src/ApiException.cs +++ b/src/ApiException.cs @@ -12,9 +12,9 @@ namespace Microsoft.Kiota.Abstractions; public class ApiException : Exception { /// - public ApiException(): base() + public ApiException() : base() { - + } /// public ApiException(string message) : base(message) @@ -24,7 +24,7 @@ public ApiException(string message) : base(message) public ApiException(string message, Exception innerException) : base(message, innerException) { } - + /// /// The HTTP response status code. /// diff --git a/src/BaseRequestBuilder.cs b/src/BaseRequestBuilder.cs index 910fec8d..ef16ed08 100644 --- a/src/BaseRequestBuilder.cs +++ b/src/BaseRequestBuilder.cs @@ -39,11 +39,11 @@ protected BaseRequestBuilder(IRequestAdapter requestAdapter, string urlTemplate, /// The request adapter to use to execute the requests. /// Url template to use to build the URL for the current request builder /// The raw URL to use for the current request builder - protected BaseRequestBuilder(IRequestAdapter requestAdapter, string urlTemplate, string rawUrl):this(requestAdapter, urlTemplate, new Dictionary() { + protected BaseRequestBuilder(IRequestAdapter requestAdapter, string urlTemplate, string rawUrl) : this(requestAdapter, urlTemplate, new Dictionary() { { RequestInformation.RawUrlKey, rawUrl } }) { - if (string.IsNullOrEmpty(rawUrl)) + if(string.IsNullOrEmpty(rawUrl)) { throw new ArgumentNullException(nameof(rawUrl)); } diff --git a/src/IResponseHandler.cs b/src/IResponseHandler.cs index 67aad082..cf3614b8 100644 --- a/src/IResponseHandler.cs +++ b/src/IResponseHandler.cs @@ -2,9 +2,9 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ -using System.Threading.Tasks; -using System.Collections.Generic; using System; +using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Kiota.Abstractions.Serialization; namespace Microsoft.Kiota.Abstractions diff --git a/src/NativeResponseHandler.cs b/src/NativeResponseHandler.cs index f83d197d..5bb7a978 100644 --- a/src/NativeResponseHandler.cs +++ b/src/NativeResponseHandler.cs @@ -2,9 +2,9 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ -using System.Threading.Tasks; -using System.Collections.Generic; using System; +using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Kiota.Abstractions.Serialization; namespace Microsoft.Kiota.Abstractions diff --git a/src/QueryParameterAttribute.cs b/src/QueryParameterAttribute.cs index 1a369abb..12d57f4c 100644 --- a/src/QueryParameterAttribute.cs +++ b/src/QueryParameterAttribute.cs @@ -12,7 +12,7 @@ namespace Microsoft.Kiota.Abstractions; public sealed class QueryParameterAttribute : Attribute { private readonly string templateName; - + /// /// Creates a new instance of the attribute /// @@ -22,7 +22,7 @@ public QueryParameterAttribute(string templateName) if(string.IsNullOrEmpty(templateName)) throw new ArgumentNullException(nameof(templateName)); this.templateName = templateName; } - + /// /// The name of the parameter in the template. /// diff --git a/src/authentication/ApiKeyAuthenticationProvider.cs b/src/authentication/ApiKeyAuthenticationProvider.cs index 9378ca81..a0e507c7 100644 --- a/src/authentication/ApiKeyAuthenticationProvider.cs +++ b/src/authentication/ApiKeyAuthenticationProvider.cs @@ -30,11 +30,11 @@ public class ApiKeyAuthenticationProvider : IAuthenticationProvider /// The hosts that are allowed to use the provided API key. public ApiKeyAuthenticationProvider(string apiKey, string parameterName, KeyLocation keyLocation, params string[] allowedHosts) { - if (string.IsNullOrEmpty(apiKey)) + if(string.IsNullOrEmpty(apiKey)) throw new ArgumentNullException(nameof(apiKey)); - if (string.IsNullOrEmpty(parameterName)) + if(string.IsNullOrEmpty(parameterName)) throw new ArgumentNullException(nameof(parameterName)); - if (allowedHosts == null) + if(allowedHosts == null) throw new ArgumentNullException(nameof(allowedHosts)); ApiKey = apiKey; ParameterName = parameterName; @@ -45,21 +45,24 @@ public ApiKeyAuthenticationProvider(string apiKey, string parameterName, KeyLoca /// public Task AuthenticateRequestAsync(RequestInformation request, Dictionary? additionalAuthenticationContext = default, CancellationToken cancellationToken = default) { - if (request == null) + if(request == null) throw new ArgumentNullException(nameof(request)); using var span = _activitySource?.StartActivity(nameof(AuthenticateRequestAsync)); - if (!AllowedHostsValidator.IsUrlHostValid(request.URI)) { + if(!AllowedHostsValidator.IsUrlHostValid(request.URI)) + { span?.SetTag("com.microsoft.kiota.authentication.is_url_valid", false); return Task.CompletedTask; } var uri = request.URI; - if(!uri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase)) { + if(!uri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase)) + { span?.SetTag("com.microsoft.kiota.authentication.is_url_valid", false); throw new ArgumentException("Only https is supported"); } - switch(KeyLoc) { + switch(KeyLoc) + { case KeyLocation.QueryParameter: var uriString = uri.OriginalString + (uri.Query != string.Empty ? "&" : "?") + $"{ParameterName}={ApiKey}"; request.URI = new Uri(uriString); @@ -76,7 +79,8 @@ public Task AuthenticateRequestAsync(RequestInformation request, Dictionary /// The location of the API key parameter. /// - public enum KeyLocation { + public enum KeyLocation + { /// /// The API key is passed as a query parameter. /// diff --git a/src/authentication/BaseBearerTokenAuthenticationProvider.cs b/src/authentication/BaseBearerTokenAuthenticationProvider.cs index ed9e6f58..bcc3e4dc 100644 --- a/src/authentication/BaseBearerTokenAuthenticationProvider.cs +++ b/src/authentication/BaseBearerTokenAuthenticationProvider.cs @@ -24,7 +24,7 @@ public BaseBearerTokenAuthenticationProvider(IAccessTokenProvider accessTokenPro /// /// Gets the to use for getting the access token. /// - public IAccessTokenProvider AccessTokenProvider {get; private set;} + public IAccessTokenProvider AccessTokenProvider { get; private set; } private const string AuthorizationHeaderKey = "Authorization"; private const string ClaimsKey = "claims"; diff --git a/src/extensions/IDictionaryExtensions.cs b/src/extensions/IDictionaryExtensions.cs index c7ca7e44..63e00180 100644 --- a/src/extensions/IDictionaryExtensions.cs +++ b/src/extensions/IDictionaryExtensions.cs @@ -28,7 +28,7 @@ public static bool TryAdd(this IDictionary dictionar { throw new ArgumentNullException(nameof(dictionary)); } - + if(key == null) { throw new ArgumentNullException(nameof(key)); diff --git a/src/serialization/ParseNodeFactoryRegistry.cs b/src/serialization/ParseNodeFactoryRegistry.cs index 8a02c1ca..231b5d2f 100644 --- a/src/serialization/ParseNodeFactoryRegistry.cs +++ b/src/serialization/ParseNodeFactoryRegistry.cs @@ -53,7 +53,7 @@ public IParseNode GetRootParseNode(string contentType, Stream content) var cleanedContentType = contentTypeVendorCleanupRegex.Replace(vendorSpecificContentType, string.Empty); if(ContentTypeAssociatedFactories.ContainsKey(cleanedContentType)) return ContentTypeAssociatedFactories[cleanedContentType].GetRootParseNode(cleanedContentType, content); - + throw new InvalidOperationException($"Content type {cleanedContentType} does not have a factory registered to be parsed"); } } diff --git a/src/serialization/ParseNodeHelper.cs b/src/serialization/ParseNodeHelper.cs index 9859795f..e6bb0415 100644 --- a/src/serialization/ParseNodeHelper.cs +++ b/src/serialization/ParseNodeHelper.cs @@ -11,13 +11,15 @@ namespace Microsoft.Kiota.Abstractions.Serialization; /// /// Helper methods for intersection wrappers /// -public static class ParseNodeHelper { +public static class ParseNodeHelper +{ /// /// Merges the given fields deserializers for an intersection type into a single collection. /// /// The collection of deserializers to merge. - public static IDictionary> MergeDeserializersForIntersectionWrapper(params IParsable?[] targets) { - if (targets == null) + public static IDictionary> MergeDeserializersForIntersectionWrapper(params IParsable?[] targets) + { + if(targets == null) { throw new ArgumentNullException(nameof(targets)); } @@ -25,7 +27,7 @@ public static IDictionary> MergeDeserializersForInter { throw new ArgumentException("At least one target must be provided.", nameof(targets)); } - + return targets.Where(static x => x != null) .SelectMany(static x => x!.GetFieldDeserializers()) .GroupBy(static x => x.Key) diff --git a/src/serialization/SerializationWriterFactoryRegistry.cs b/src/serialization/SerializationWriterFactoryRegistry.cs index 43a7a799..6ba7bce5 100644 --- a/src/serialization/SerializationWriterFactoryRegistry.cs +++ b/src/serialization/SerializationWriterFactoryRegistry.cs @@ -44,7 +44,7 @@ public ISerializationWriter GetSerializationWriter(string contentType) var vendorSpecificContentType = contentType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).First(); if(ContentTypeAssociatedFactories.ContainsKey(vendorSpecificContentType)) return ContentTypeAssociatedFactories[vendorSpecificContentType].GetSerializationWriter(vendorSpecificContentType); - + var cleanedContentType = ParseNodeFactoryRegistry.contentTypeVendorCleanupRegex.Replace(vendorSpecificContentType, string.Empty); if(ContentTypeAssociatedFactories.ContainsKey(cleanedContentType)) return ContentTypeAssociatedFactories[cleanedContentType].GetSerializationWriter(cleanedContentType); diff --git a/src/store/InMemoryBackingStore.cs b/src/store/InMemoryBackingStore.cs index 152b3f6d..adc5c187 100644 --- a/src/store/InMemoryBackingStore.cs +++ b/src/store/InMemoryBackingStore.cs @@ -74,7 +74,7 @@ public void Set(string key, T? value) { backedModel.BackingStore.InitializationCompleted = false;// All its properties are dirty as the model has been touched. Set(key, value); - },key); // use property name(key) as subscriptionId to prevent excess subscription creation in the event this is called again + }, key); // use property name(key) as subscriptionId to prevent excess subscription creation in the event this is called again } // if its an IBackedModel collection property to the store, subscribe to item properties' BackingStores and use the events to flag the collection property is "dirty" if(value is ICollection collectionValues) @@ -86,7 +86,7 @@ public void Set(string key, T? value) model.BackingStore.Subscribe((keyString, oldObject, newObject) => { Set(key, value); - },key);// use property name(key) as subscriptionId to prevent excess subscription creation in the event this is called again + }, key);// use property name(key) as subscriptionId to prevent excess subscription creation in the event this is called again }); } @@ -101,7 +101,7 @@ public void Set(string key, T? value) public IEnumerable> Enumerate() { if(ReturnOnlyChangedValues)// refresh the state of collection properties if they've changed in size. - store.ToList().ForEach(x => EnsureCollectionPropertyIsConsistent(x.Key,x.Value.Item2)); + store.ToList().ForEach(x => EnsureCollectionPropertyIsConsistent(x.Key, x.Value.Item2)); return (ReturnOnlyChangedValues ? store.Where(x => x.Value.Item1) : store) .Select(x => new KeyValuePair(x.Key, x.Value.Item2)); @@ -140,7 +140,7 @@ public void Subscribe(Action callback, string subscrip throw new ArgumentNullException(nameof(subscriptionId)); if(callback == null) throw new ArgumentNullException(nameof(callback)); - subscriptions.AddOrUpdate(subscriptionId, callback, (_,_) => callback); + subscriptions.AddOrUpdate(subscriptionId, callback, (_, _) => callback); } /// @@ -184,7 +184,7 @@ private void EnsureCollectionPropertyIsConsistent(string key, object? storeItem) // Call Get<>() on nested properties so that this method may be called recursively to ensure collections are consistent collectionTuple.Item1.OfType().ToList().ForEach(store => store.BackingStore.Enumerate() .ToList().ForEach(item => store.BackingStore.Get(item.Key))); - + if(collectionTuple.Item2 != collectionTuple.Item1.Count) // and the size has changed since we last updated) { Set(key, collectionTuple.Item1); //ensure the store is notified the collection property is "dirty" From f1389bb9f18bca78e3a516000bc902c59a554f37 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 27 Oct 2023 14:45:01 -0400 Subject: [PATCH 02/11] - adds object deserialization helpers Signed-off-by: Vincent Biret --- .../Serialization/Mocks/TestEntity.cs | 74 +++++++++++++++ .../SerializationHelpersTests.cs | 59 ++++++++++++ src/serialization/SerializationHelpers.cs | 90 +++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 Microsoft.Kiota.Abstractions.Tests/Serialization/Mocks/TestEntity.cs create mode 100644 Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs create mode 100644 src/serialization/SerializationHelpers.cs diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/Mocks/TestEntity.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/Mocks/TestEntity.cs new file mode 100644 index 00000000..958ddca4 --- /dev/null +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/Mocks/TestEntity.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using Microsoft.Kiota.Abstractions.Serialization; + +namespace Microsoft.Kiota.Abstractions.Tests.Serialization.Mocks +{ + public class TestEntity : IParsable, IAdditionalDataHolder + { + /// Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well. + public IDictionary AdditionalData { get; set; } + /// Read-only. + public string Id { get; set; } + /// Read-only. + public TimeSpan? WorkDuration { get; set; } + /// Read-only. + public Date? BirthDay { get; set; } + /// Read-only. + public Time? StartWorkTime { get; set; } + /// Read-only. + public Time? EndWorkTime { get; set; } + /// Read-only. + public DateTimeOffset? CreatedDateTime { get; set; } + /// Read-only. + public string OfficeLocation { get; set; } + /// + /// Instantiates a new entity and sets the default values. + /// + public TestEntity() + { + AdditionalData = new Dictionary(); + } + /// + /// The deserialization information for the current model + /// + public virtual IDictionary> GetFieldDeserializers() + { + return new Dictionary> { + {"id", n => { Id = n.GetStringValue(); } }, + {"createdDateTime", n => { CreatedDateTime = n.GetDateTimeOffsetValue(); } }, + {"officeLocation", n => { OfficeLocation = n.GetStringValue(); } }, + {"workDuration", n => { WorkDuration = n.GetTimeSpanValue(); } }, + {"birthDay", n => { BirthDay = n.GetDateValue(); } }, + {"startWorkTime", n => { StartWorkTime = n.GetTimeValue(); } }, + {"endWorkTime", n => { EndWorkTime = n.GetTimeValue(); } }, + }; + } + /// + /// Serializes information the current object + /// Serialization writer to use to serialize this model + /// + public virtual void Serialize(ISerializationWriter writer) + { + _ = writer ?? throw new ArgumentNullException(nameof(writer)); + writer.WriteStringValue("id", Id); + writer.WriteDateTimeOffsetValue("createdDateTime", CreatedDateTime); + writer.WriteStringValue("officeLocation", OfficeLocation); + writer.WriteTimeSpanValue("workDuration", WorkDuration); + writer.WriteDateValue("birthDay", BirthDay); + writer.WriteTimeValue("startWorkTime", StartWorkTime); + writer.WriteTimeValue("endWorkTime", EndWorkTime); + writer.WriteAdditionalData(AdditionalData); + } + public static TestEntity CreateFromDiscriminator(IParseNode parseNode) + { + var discriminatorValue = parseNode.GetChildNode("@odata.type")?.GetStringValue(); + return discriminatorValue switch + { + "microsoft.graph.user" => new TestEntity(), + "microsoft.graph.group" => new TestEntity(), + _ => new TestEntity(), + }; + } + } +} diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs new file mode 100644 index 00000000..4d299e66 --- /dev/null +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Tests.Mocks; +using Moq; +using Xunit; + +namespace Microsoft.Kiota.Abstractions.Tests.Serialization; + +public class SerializationHelpersTests +{ + private const string _jsonContentType = "application/json"; + [Fact] + public void Defensive() + { + Assert.Throws(() => SerializationHelpers.Deserialize(null, (Stream)null, null)); + Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, (Stream)null, null)); + using var stream = new MemoryStream(); + Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, stream, null)); + Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, "", null)); + Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, stream, TestEntity.CreateFromDiscriminatorValue)); + } + [Fact] + public void DeserializesObjectWithoutReflection() + { + var strValue = "{'id':'123'}"; + var mockParseNode = new Mock(); + mockParseNode.Setup(x => x.GetObjectValue(It.IsAny>())).Returns(new TestEntity() + { + Id = "123" + }); + var mockJsonParseNodeFactory = new Mock(); + mockJsonParseNodeFactory.Setup(x => x.GetRootParseNode(It.IsAny(), It.IsAny())).Returns(mockParseNode.Object); + mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); + ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; + + var result = SerializationHelpers.Deserialize(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); + + Assert.NotNull(result); + } + [Fact] + public void DeserializesObjectWithReflection() + { + var strValue = "{'id':'123'}"; + var mockParseNode = new Mock(); + mockParseNode.Setup(x => x.GetObjectValue(It.IsAny>())).Returns(new TestEntity() + { + Id = "123" + }); + var mockJsonParseNodeFactory = new Mock(); + mockJsonParseNodeFactory.Setup(x => x.GetRootParseNode(It.IsAny(), It.IsAny())).Returns(mockParseNode.Object); + mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); + ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; + + var result = SerializationHelpers.Deserialize(_jsonContentType, strValue); + + Assert.NotNull(result); + } +} diff --git a/src/serialization/SerializationHelpers.cs b/src/serialization/SerializationHelpers.cs new file mode 100644 index 00000000..ee55d17c --- /dev/null +++ b/src/serialization/SerializationHelpers.cs @@ -0,0 +1,90 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ + +using System; +using System.IO; +using System.Linq; +using System.Text; +#if NET5_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + + +namespace Microsoft.Kiota.Abstractions.Serialization; + +/// +/// Set of helper methods for serialization +/// +public static class SerializationHelpers +{ + /// + /// Deserializes the given stream into a object based on the content type. + /// + /// The content type of the stream. + /// The factory to create the object. + /// The serialized representation of the object. + public static T Deserialize(string contentType, string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable + { + if(string.IsNullOrEmpty(serializedRepresentation)) throw new ArgumentNullException(nameof(serializedRepresentation)); + using var stream = GetStreamFromString(serializedRepresentation); + return Deserialize(contentType, stream, parsableFactory); + } + private static Stream GetStreamFromString(string source) + { + var stream = new MemoryStream(); + using var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true); + writer.WriteAsync(source).GetAwaiter().GetResult(); // so the asp.net projects don't get an error + writer.Flush(); + stream.Position = 0; + return stream; + } + /// + /// Deserializes the given stream into a object based on the content type. + /// + /// The content type of the stream. + /// The stream to deserialize. + /// The factory to create the object. + public static T Deserialize(string contentType, Stream stream, ParsableFactory parsableFactory) where T : IParsable + { + if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); + if(stream == null) throw new ArgumentNullException(nameof(stream)); + if(parsableFactory == null) throw new ArgumentNullException(nameof(parsableFactory)); + var parseNode = ParseNodeFactoryRegistry.DefaultInstance.GetRootParseNode(contentType, stream); + return parsableFactory(parseNode); + } + /// + /// Deserializes the given stream into a object based on the content type. + /// + /// The content type of the stream. + /// The stream to deserialize. +#if NET5_0_OR_GREATER + public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, Stream stream) where T : IParsable +#else + public static T Deserialize(string contentType, Stream stream) where T : IParsable +#endif + => Deserialize(contentType, stream, GetFactoryFromType()); +#if NET5_0_OR_GREATER + private static ParsableFactory GetFactoryFromType<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() where T : IParsable +#else + private static ParsableFactory GetFactoryFromType() where T : IParsable +#endif + { + var type = typeof(T); + var factoryMethod = type.GetMethods().Where(static x => x.IsStatic && "CreateFromDiscriminatorValue".Equals(x.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault() ?? + throw new InvalidOperationException($"No factory method found for type {type.Name}"); + return (ParsableFactory)factoryMethod.CreateDelegate(typeof(ParsableFactory)); + } + /// + /// Deserializes the given stream into a object based on the content type. + /// + /// The content type of the stream. + /// The serialized representation of the object. +#if NET5_0_OR_GREATER + public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, string serializedRepresentation) where T : IParsable +#else + public static T Deserialize(string contentType, string serializedRepresentation) where T : IParsable +#endif + => Deserialize(contentType, serializedRepresentation, GetFactoryFromType()); + +} \ No newline at end of file From 3cda3e9c89b57da8212e8d89f5ca9e756d76b1be Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 27 Oct 2023 14:51:15 -0400 Subject: [PATCH 03/11] - adds json helpers --- src/serialization/JsonSerializationHelpers.cs | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/serialization/JsonSerializationHelpers.cs diff --git a/src/serialization/JsonSerializationHelpers.cs b/src/serialization/JsonSerializationHelpers.cs new file mode 100644 index 00000000..7e37964c --- /dev/null +++ b/src/serialization/JsonSerializationHelpers.cs @@ -0,0 +1,52 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ + +using System.IO; +#if NET5_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + +namespace Microsoft.Kiota.Abstractions.Serialization; + +/// +/// Set of helper methods for JSON serialization +/// +public class JsonSerializationHelpers +{ + private const string _jsonContentType = "application/json"; + /// + /// Deserializes the given stream into a object. + /// + /// The factory to create the object. + /// The serialized representation of the object. + public static T Deserialize(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable + => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation, parsableFactory); + /// + /// Deserializes the given stream into a object based on the content type. + /// + /// The stream to deserialize. + /// The factory to create the object. + public static T Deserialize(Stream stream, ParsableFactory parsableFactory) where T : IParsable + => SerializationHelpers.Deserialize(_jsonContentType, stream, parsableFactory); + /// + /// Deserializes the given stream into a object based on the content type. + /// + /// The stream to deserialize. +#if NET5_0_OR_GREATER + public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(Stream stream) where T : IParsable +#else + public static T Deserialize(Stream stream) where T : IParsable +#endif + => SerializationHelpers.Deserialize(_jsonContentType, stream); + /// + /// Deserializes the given stream into a object based on the content type. + /// + /// The serialized representation of the object. +#if NET5_0_OR_GREATER + public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string serializedRepresentation) where T : IParsable +#else + public static T Deserialize(string serializedRepresentation) where T : IParsable +#endif + => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation); +} \ No newline at end of file From 8caf8eba9107ca5264917dfed72ea25139438c33 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 27 Oct 2023 14:58:00 -0400 Subject: [PATCH 04/11] - fixes deserialization implementation Signed-off-by: Vincent Biret --- .../Serialization/SerializationHelpersTests.cs | 1 - src/serialization/JsonSerializationHelpers.cs | 12 ++++++------ src/serialization/SerializationHelpers.cs | 14 +++++++------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs index 4d299e66..dc2924e6 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs @@ -18,7 +18,6 @@ public void Defensive() using var stream = new MemoryStream(); Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, stream, null)); Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, "", null)); - Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, stream, TestEntity.CreateFromDiscriminatorValue)); } [Fact] public void DeserializesObjectWithoutReflection() diff --git a/src/serialization/JsonSerializationHelpers.cs b/src/serialization/JsonSerializationHelpers.cs index 7e37964c..274b84ea 100644 --- a/src/serialization/JsonSerializationHelpers.cs +++ b/src/serialization/JsonSerializationHelpers.cs @@ -20,23 +20,23 @@ public class JsonSerializationHelpers /// /// The factory to create the object. /// The serialized representation of the object. - public static T Deserialize(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable + public static T? Deserialize(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation, parsableFactory); /// /// Deserializes the given stream into a object based on the content type. /// /// The stream to deserialize. /// The factory to create the object. - public static T Deserialize(Stream stream, ParsableFactory parsableFactory) where T : IParsable + public static T? Deserialize(Stream stream, ParsableFactory parsableFactory) where T : IParsable => SerializationHelpers.Deserialize(_jsonContentType, stream, parsableFactory); /// /// Deserializes the given stream into a object based on the content type. /// /// The stream to deserialize. #if NET5_0_OR_GREATER - public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(Stream stream) where T : IParsable + public static T? Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(Stream stream) where T : IParsable #else - public static T Deserialize(Stream stream) where T : IParsable + public static T? Deserialize(Stream stream) where T : IParsable #endif => SerializationHelpers.Deserialize(_jsonContentType, stream); /// @@ -44,9 +44,9 @@ public static T Deserialize(Stream stream) where T : IParsable /// /// The serialized representation of the object. #if NET5_0_OR_GREATER - public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string serializedRepresentation) where T : IParsable + public static T? Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string serializedRepresentation) where T : IParsable #else - public static T Deserialize(string serializedRepresentation) where T : IParsable + public static T? Deserialize(string serializedRepresentation) where T : IParsable #endif => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation); } \ No newline at end of file diff --git a/src/serialization/SerializationHelpers.cs b/src/serialization/SerializationHelpers.cs index ee55d17c..8e2b2ef9 100644 --- a/src/serialization/SerializationHelpers.cs +++ b/src/serialization/SerializationHelpers.cs @@ -24,7 +24,7 @@ public static class SerializationHelpers /// The content type of the stream. /// The factory to create the object. /// The serialized representation of the object. - public static T Deserialize(string contentType, string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable + public static T? Deserialize(string contentType, string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable { if(string.IsNullOrEmpty(serializedRepresentation)) throw new ArgumentNullException(nameof(serializedRepresentation)); using var stream = GetStreamFromString(serializedRepresentation); @@ -45,13 +45,13 @@ private static Stream GetStreamFromString(string source) /// The content type of the stream. /// The stream to deserialize. /// The factory to create the object. - public static T Deserialize(string contentType, Stream stream, ParsableFactory parsableFactory) where T : IParsable + public static T? Deserialize(string contentType, Stream stream, ParsableFactory parsableFactory) where T : IParsable { if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); if(stream == null) throw new ArgumentNullException(nameof(stream)); if(parsableFactory == null) throw new ArgumentNullException(nameof(parsableFactory)); var parseNode = ParseNodeFactoryRegistry.DefaultInstance.GetRootParseNode(contentType, stream); - return parsableFactory(parseNode); + return parseNode.GetObjectValue(parsableFactory); } /// /// Deserializes the given stream into a object based on the content type. @@ -59,9 +59,9 @@ public static T Deserialize(string contentType, Stream stream, ParsableFactor /// The content type of the stream. /// The stream to deserialize. #if NET5_0_OR_GREATER - public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, Stream stream) where T : IParsable + public static T? Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, Stream stream) where T : IParsable #else - public static T Deserialize(string contentType, Stream stream) where T : IParsable + public static T? Deserialize(string contentType, Stream stream) where T : IParsable #endif => Deserialize(contentType, stream, GetFactoryFromType()); #if NET5_0_OR_GREATER @@ -81,9 +81,9 @@ private static ParsableFactory GetFactoryFromType() where T : IParsable /// The content type of the stream. /// The serialized representation of the object. #if NET5_0_OR_GREATER - public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, string serializedRepresentation) where T : IParsable + public static T? Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, string serializedRepresentation) where T : IParsable #else - public static T Deserialize(string contentType, string serializedRepresentation) where T : IParsable + public static T? Deserialize(string contentType, string serializedRepresentation) where T : IParsable #endif => Deserialize(contentType, serializedRepresentation, GetFactoryFromType()); From 393145099029672635718649dc43bcee92b0e86e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 27 Oct 2023 15:09:45 -0400 Subject: [PATCH 05/11] - adds deserialization for collections --- .../SerializationHelpersTests.cs | 33 ++++++++++- src/serialization/JsonSerializationHelpers.cs | 43 ++++++++++++-- src/serialization/SerializationHelpers.cs | 57 +++++++++++++++++-- 3 files changed, 124 insertions(+), 9 deletions(-) diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs index dc2924e6..c1abf44a 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using Microsoft.Kiota.Abstractions.Serialization; using Microsoft.Kiota.Abstractions.Tests.Mocks; @@ -11,7 +12,7 @@ public class SerializationHelpersTests { private const string _jsonContentType = "application/json"; [Fact] - public void Defensive() + public void DefensiveObject() { Assert.Throws(() => SerializationHelpers.Deserialize(null, (Stream)null, null)); Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, (Stream)null, null)); @@ -20,6 +21,15 @@ public void Defensive() Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, "", null)); } [Fact] + public void DefensiveObjectCollection() + { + Assert.Throws(() => SerializationHelpers.DeserializeCollection(null, (Stream)null, null)); + Assert.Throws(() => SerializationHelpers.DeserializeCollection(_jsonContentType, (Stream)null, null)); + using var stream = new MemoryStream(); + Assert.Throws(() => SerializationHelpers.DeserializeCollection(_jsonContentType, stream, null)); + Assert.Throws(() => SerializationHelpers.DeserializeCollection(_jsonContentType, "", null)); + } + [Fact] public void DeserializesObjectWithoutReflection() { var strValue = "{'id':'123'}"; @@ -55,4 +65,25 @@ public void DeserializesObjectWithReflection() Assert.NotNull(result); } + [Fact] + public void DeserializesCollectionOfObject() + { + var strValue = "{'id':'123'}"; + var mockParseNode = new Mock(); + mockParseNode.Setup(x => x.GetCollectionOfObjectValues(It.IsAny>())).Returns(new List { + new TestEntity() + { + Id = "123" + } + }); + var mockJsonParseNodeFactory = new Mock(); + mockJsonParseNodeFactory.Setup(x => x.GetRootParseNode(It.IsAny(), It.IsAny())).Returns(mockParseNode.Object); + mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); + ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; + + var result = SerializationHelpers.DeserializeCollection(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); + + Assert.NotNull(result); + Assert.Single(result); + } } diff --git a/src/serialization/JsonSerializationHelpers.cs b/src/serialization/JsonSerializationHelpers.cs index 274b84ea..2ea5732e 100644 --- a/src/serialization/JsonSerializationHelpers.cs +++ b/src/serialization/JsonSerializationHelpers.cs @@ -2,6 +2,7 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ +using System.Collections.Generic; using System.IO; #if NET5_0_OR_GREATER using System.Diagnostics.CodeAnalysis; @@ -16,21 +17,21 @@ public class JsonSerializationHelpers { private const string _jsonContentType = "application/json"; /// - /// Deserializes the given stream into a object. + /// Deserializes the given stream into an object. /// /// The factory to create the object. /// The serialized representation of the object. public static T? Deserialize(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation, parsableFactory); /// - /// Deserializes the given stream into a object based on the content type. + /// Deserializes the given stream into an object. /// /// The stream to deserialize. /// The factory to create the object. public static T? Deserialize(Stream stream, ParsableFactory parsableFactory) where T : IParsable => SerializationHelpers.Deserialize(_jsonContentType, stream, parsableFactory); /// - /// Deserializes the given stream into a object based on the content type. + /// Deserializes the given stream into an object. /// /// The stream to deserialize. #if NET5_0_OR_GREATER @@ -40,7 +41,7 @@ public class JsonSerializationHelpers #endif => SerializationHelpers.Deserialize(_jsonContentType, stream); /// - /// Deserializes the given stream into a object based on the content type. + /// Deserializes the given stream into an object. /// /// The serialized representation of the object. #if NET5_0_OR_GREATER @@ -49,4 +50,38 @@ public class JsonSerializationHelpers public static T? Deserialize(string serializedRepresentation) where T : IParsable #endif => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation); + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The stream to deserialize. + /// The factory to create the object. + public static IEnumerable DeserializeCollection(Stream stream, ParsableFactory parsableFactory) where T : IParsable + => SerializationHelpers.DeserializeCollection(_jsonContentType, stream, parsableFactory); + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The serialized representation of the objects. + /// The factory to create the object. + public static IEnumerable DeserializeCollection(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable + => SerializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation, parsableFactory); + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The stream to deserialize. +#if NET5_0_OR_GREATER + public static IEnumerable DeserializeCollection<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(Stream stream) where T : IParsable +#else + public static IEnumerable DeserializeCollection(Stream stream) where T : IParsable +#endif + => SerializationHelpers.DeserializeCollection(_jsonContentType, stream); + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The serialized representation of the object. +#if NET5_0_OR_GREATER + public static IEnumerable DeserializeCollection<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string serializedRepresentation) where T : IParsable +#else + public static IEnumerable DeserializeCollection(string serializedRepresentation) where T : IParsable +#endif + => SerializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation); } \ No newline at end of file diff --git a/src/serialization/SerializationHelpers.cs b/src/serialization/SerializationHelpers.cs index 8e2b2ef9..f14a4c1e 100644 --- a/src/serialization/SerializationHelpers.cs +++ b/src/serialization/SerializationHelpers.cs @@ -3,6 +3,7 @@ // ------------------------------------------------------------------------------ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -19,7 +20,7 @@ namespace Microsoft.Kiota.Abstractions.Serialization; public static class SerializationHelpers { /// - /// Deserializes the given stream into a object based on the content type. + /// Deserializes the given stream into an object based on the content type. /// /// The content type of the stream. /// The factory to create the object. @@ -40,7 +41,7 @@ private static Stream GetStreamFromString(string source) return stream; } /// - /// Deserializes the given stream into a object based on the content type. + /// Deserializes the given stream into an object based on the content type. /// /// The content type of the stream. /// The stream to deserialize. @@ -54,7 +55,7 @@ private static Stream GetStreamFromString(string source) return parseNode.GetObjectValue(parsableFactory); } /// - /// Deserializes the given stream into a object based on the content type. + /// Deserializes the given stream into an object based on the content type. /// /// The content type of the stream. /// The stream to deserialize. @@ -76,7 +77,7 @@ private static ParsableFactory GetFactoryFromType() where T : IParsable return (ParsableFactory)factoryMethod.CreateDelegate(typeof(ParsableFactory)); } /// - /// Deserializes the given stream into a object based on the content type. + /// Deserializes the given stream into an object based on the content type. /// /// The content type of the stream. /// The serialized representation of the object. @@ -87,4 +88,52 @@ private static ParsableFactory GetFactoryFromType() where T : IParsable #endif => Deserialize(contentType, serializedRepresentation, GetFactoryFromType()); + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The content type of the stream. + /// The stream to deserialize. + /// The factory to create the object. + public static IEnumerable DeserializeCollection(string contentType, Stream stream, ParsableFactory parsableFactory) where T : IParsable + { + if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); + if(stream == null) throw new ArgumentNullException(nameof(stream)); + if(parsableFactory == null) throw new ArgumentNullException(nameof(parsableFactory)); + var parseNode = ParseNodeFactoryRegistry.DefaultInstance.GetRootParseNode(contentType, stream); + return parseNode.GetCollectionOfObjectValues(parsableFactory); + } + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The content type of the stream. + /// The serialized representation of the objects. + /// The factory to create the object. + public static IEnumerable DeserializeCollection(string contentType, string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable + { + if(string.IsNullOrEmpty(serializedRepresentation)) throw new ArgumentNullException(nameof(serializedRepresentation)); + using var stream = GetStreamFromString(serializedRepresentation); + return DeserializeCollection(contentType, stream, parsableFactory); + } + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The content type of the stream. + /// The stream to deserialize. +#if NET5_0_OR_GREATER + public static IEnumerable DeserializeCollection<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, Stream stream) where T : IParsable +#else + public static IEnumerable DeserializeCollection(string contentType, Stream stream) where T : IParsable +#endif + => DeserializeCollection(contentType, stream, GetFactoryFromType()); + /// + /// Deserializes the given stream into a collection of objects based on the content type. + /// + /// The content type of the stream. + /// The serialized representation of the object. +#if NET5_0_OR_GREATER + public static IEnumerable DeserializeCollection<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(string contentType, string serializedRepresentation) where T : IParsable +#else + public static IEnumerable DeserializeCollection(string contentType, string serializedRepresentation) where T : IParsable +#endif + => DeserializeCollection(contentType, serializedRepresentation, GetFactoryFromType()); } \ No newline at end of file From 4f1c7a800787aa0ee5a9d8549c625091fd226219 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 27 Oct 2023 15:12:06 -0400 Subject: [PATCH 06/11] - normalizes naming for helpers --- ...ests.cs => DeserializationHelpersTests.cs} | 24 +++++++++---------- ...onHelpers.cs => DeserializationHelpers.cs} | 2 +- ...lpers.cs => JsonDeserializationHelpers.cs} | 18 +++++++------- 3 files changed, 22 insertions(+), 22 deletions(-) rename Microsoft.Kiota.Abstractions.Tests/Serialization/{SerializationHelpersTests.cs => DeserializationHelpersTests.cs} (67%) rename src/serialization/{SerializationHelpers.cs => DeserializationHelpers.cs} (99%) rename src/serialization/{JsonSerializationHelpers.cs => JsonDeserializationHelpers.cs} (84%) diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/DeserializationHelpersTests.cs similarity index 67% rename from Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs rename to Microsoft.Kiota.Abstractions.Tests/Serialization/DeserializationHelpersTests.cs index c1abf44a..7cb78fb6 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/DeserializationHelpersTests.cs @@ -8,26 +8,26 @@ namespace Microsoft.Kiota.Abstractions.Tests.Serialization; -public class SerializationHelpersTests +public class DeserializationHelpersTests { private const string _jsonContentType = "application/json"; [Fact] public void DefensiveObject() { - Assert.Throws(() => SerializationHelpers.Deserialize(null, (Stream)null, null)); - Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, (Stream)null, null)); + Assert.Throws(() => DeserializationHelpers.Deserialize(null, (Stream)null, null)); + Assert.Throws(() => DeserializationHelpers.Deserialize(_jsonContentType, (Stream)null, null)); using var stream = new MemoryStream(); - Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, stream, null)); - Assert.Throws(() => SerializationHelpers.Deserialize(_jsonContentType, "", null)); + Assert.Throws(() => DeserializationHelpers.Deserialize(_jsonContentType, stream, null)); + Assert.Throws(() => DeserializationHelpers.Deserialize(_jsonContentType, "", null)); } [Fact] public void DefensiveObjectCollection() { - Assert.Throws(() => SerializationHelpers.DeserializeCollection(null, (Stream)null, null)); - Assert.Throws(() => SerializationHelpers.DeserializeCollection(_jsonContentType, (Stream)null, null)); + Assert.Throws(() => DeserializationHelpers.DeserializeCollection(null, (Stream)null, null)); + Assert.Throws(() => DeserializationHelpers.DeserializeCollection(_jsonContentType, (Stream)null, null)); using var stream = new MemoryStream(); - Assert.Throws(() => SerializationHelpers.DeserializeCollection(_jsonContentType, stream, null)); - Assert.Throws(() => SerializationHelpers.DeserializeCollection(_jsonContentType, "", null)); + Assert.Throws(() => DeserializationHelpers.DeserializeCollection(_jsonContentType, stream, null)); + Assert.Throws(() => DeserializationHelpers.DeserializeCollection(_jsonContentType, "", null)); } [Fact] public void DeserializesObjectWithoutReflection() @@ -43,7 +43,7 @@ public void DeserializesObjectWithoutReflection() mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; - var result = SerializationHelpers.Deserialize(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); + var result = DeserializationHelpers.Deserialize(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); Assert.NotNull(result); } @@ -61,7 +61,7 @@ public void DeserializesObjectWithReflection() mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; - var result = SerializationHelpers.Deserialize(_jsonContentType, strValue); + var result = DeserializationHelpers.Deserialize(_jsonContentType, strValue); Assert.NotNull(result); } @@ -81,7 +81,7 @@ public void DeserializesCollectionOfObject() mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; - var result = SerializationHelpers.DeserializeCollection(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); + var result = DeserializationHelpers.DeserializeCollection(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); Assert.NotNull(result); Assert.Single(result); diff --git a/src/serialization/SerializationHelpers.cs b/src/serialization/DeserializationHelpers.cs similarity index 99% rename from src/serialization/SerializationHelpers.cs rename to src/serialization/DeserializationHelpers.cs index f14a4c1e..5e790f54 100644 --- a/src/serialization/SerializationHelpers.cs +++ b/src/serialization/DeserializationHelpers.cs @@ -17,7 +17,7 @@ namespace Microsoft.Kiota.Abstractions.Serialization; /// /// Set of helper methods for serialization /// -public static class SerializationHelpers +public static class DeserializationHelpers { /// /// Deserializes the given stream into an object based on the content type. diff --git a/src/serialization/JsonSerializationHelpers.cs b/src/serialization/JsonDeserializationHelpers.cs similarity index 84% rename from src/serialization/JsonSerializationHelpers.cs rename to src/serialization/JsonDeserializationHelpers.cs index 2ea5732e..4a4147fc 100644 --- a/src/serialization/JsonSerializationHelpers.cs +++ b/src/serialization/JsonDeserializationHelpers.cs @@ -13,7 +13,7 @@ namespace Microsoft.Kiota.Abstractions.Serialization; /// /// Set of helper methods for JSON serialization /// -public class JsonSerializationHelpers +public class JsonDeserializationHelpers { private const string _jsonContentType = "application/json"; /// @@ -22,14 +22,14 @@ public class JsonSerializationHelpers /// The factory to create the object. /// The serialized representation of the object. public static T? Deserialize(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable - => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation, parsableFactory); + => DeserializationHelpers.Deserialize(_jsonContentType, serializedRepresentation, parsableFactory); /// /// Deserializes the given stream into an object. /// /// The stream to deserialize. /// The factory to create the object. public static T? Deserialize(Stream stream, ParsableFactory parsableFactory) where T : IParsable - => SerializationHelpers.Deserialize(_jsonContentType, stream, parsableFactory); + => DeserializationHelpers.Deserialize(_jsonContentType, stream, parsableFactory); /// /// Deserializes the given stream into an object. /// @@ -39,7 +39,7 @@ public class JsonSerializationHelpers #else public static T? Deserialize(Stream stream) where T : IParsable #endif - => SerializationHelpers.Deserialize(_jsonContentType, stream); + => DeserializationHelpers.Deserialize(_jsonContentType, stream); /// /// Deserializes the given stream into an object. /// @@ -49,21 +49,21 @@ public class JsonSerializationHelpers #else public static T? Deserialize(string serializedRepresentation) where T : IParsable #endif - => SerializationHelpers.Deserialize(_jsonContentType, serializedRepresentation); + => DeserializationHelpers.Deserialize(_jsonContentType, serializedRepresentation); /// /// Deserializes the given stream into a collection of objects based on the content type. /// /// The stream to deserialize. /// The factory to create the object. public static IEnumerable DeserializeCollection(Stream stream, ParsableFactory parsableFactory) where T : IParsable - => SerializationHelpers.DeserializeCollection(_jsonContentType, stream, parsableFactory); + => DeserializationHelpers.DeserializeCollection(_jsonContentType, stream, parsableFactory); /// /// Deserializes the given stream into a collection of objects based on the content type. /// /// The serialized representation of the objects. /// The factory to create the object. public static IEnumerable DeserializeCollection(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable - => SerializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation, parsableFactory); + => DeserializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation, parsableFactory); /// /// Deserializes the given stream into a collection of objects based on the content type. /// @@ -73,7 +73,7 @@ public static IEnumerable DeserializeCollection(string serializedRepresent #else public static IEnumerable DeserializeCollection(Stream stream) where T : IParsable #endif - => SerializationHelpers.DeserializeCollection(_jsonContentType, stream); + => DeserializationHelpers.DeserializeCollection(_jsonContentType, stream); /// /// Deserializes the given stream into a collection of objects based on the content type. /// @@ -83,5 +83,5 @@ public static IEnumerable DeserializeCollection(Stream stream) where T : I #else public static IEnumerable DeserializeCollection(string serializedRepresentation) where T : IParsable #endif - => SerializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation); + => DeserializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation); } \ No newline at end of file From 5d429e7286ed4b8abe2efdf5cba2281b8f5dc558 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 27 Oct 2023 15:32:22 -0400 Subject: [PATCH 07/11] - code linting Signed-off-by: Vincent Biret --- src/serialization/DeserializationHelpers.cs | 2 +- src/serialization/JsonDeserializationHelpers.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/serialization/DeserializationHelpers.cs b/src/serialization/DeserializationHelpers.cs index 5e790f54..74ee97c1 100644 --- a/src/serialization/DeserializationHelpers.cs +++ b/src/serialization/DeserializationHelpers.cs @@ -72,7 +72,7 @@ private static ParsableFactory GetFactoryFromType() where T : IParsable #endif { var type = typeof(T); - var factoryMethod = type.GetMethods().Where(static x => x.IsStatic && "CreateFromDiscriminatorValue".Equals(x.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault() ?? + var factoryMethod = type.GetMethods().FirstOrDefault(static x => x.IsStatic && "CreateFromDiscriminatorValue".Equals(x.Name, StringComparison.OrdinalIgnoreCase)) ?? throw new InvalidOperationException($"No factory method found for type {type.Name}"); return (ParsableFactory)factoryMethod.CreateDelegate(typeof(ParsableFactory)); } diff --git a/src/serialization/JsonDeserializationHelpers.cs b/src/serialization/JsonDeserializationHelpers.cs index 4a4147fc..958b699c 100644 --- a/src/serialization/JsonDeserializationHelpers.cs +++ b/src/serialization/JsonDeserializationHelpers.cs @@ -13,7 +13,7 @@ namespace Microsoft.Kiota.Abstractions.Serialization; /// /// Set of helper methods for JSON serialization /// -public class JsonDeserializationHelpers +public static class JsonDeserializationHelpers { private const string _jsonContentType = "application/json"; /// From 0b752435c72aaa149714c24f40120ed997b4bc75 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 30 Oct 2023 15:34:22 -0400 Subject: [PATCH 08/11] - adds serialization helpers Signed-off-by: Vincent Biret --- .../SerializationHelpersTests.cs | 69 ++++++++++++++++ src/serialization/JsonSerializationHelpers.cs | 55 +++++++++++++ src/serialization/SerializationHelpers.cs | 81 +++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs create mode 100644 src/serialization/JsonSerializationHelpers.cs create mode 100644 src/serialization/SerializationHelpers.cs diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs new file mode 100644 index 00000000..4d72605e --- /dev/null +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Microsoft.Kiota.Abstractions.Serialization; +using Microsoft.Kiota.Abstractions.Tests.Mocks; +using Moq; +using Xunit; + +namespace Microsoft.Kiota.Abstractions.Tests.Serialization; + +public class SerializationHelpersTests +{ + private const string _jsonContentType = "application/json"; + [Fact] + public void DefensiveObject() + { + Assert.Throws(() => SerializationHelpers.SerializeAsStream(null, (TestEntity)null)); + Assert.Throws(() => SerializationHelpers.SerializeAsStream(_jsonContentType, (TestEntity)null)); + } + [Fact] + public void DefensiveObjectCollection() + { + Assert.Throws(() => SerializationHelpers.SerializeAsStream(null, (IEnumerable)null)); + Assert.Throws(() => SerializationHelpers.SerializeAsStream(_jsonContentType, (IEnumerable)null)); + } + [Fact] + public void SerializesObject() + { + var mockSerializationWriter = new Mock(); + mockSerializationWriter.Setup(x => x.GetSerializedContent()).Returns(new MemoryStream(UTF8Encoding.UTF8.GetBytes("{'id':'123'}"))); + var mockSerializationWriterFactory = new Mock(); + mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny())).Returns(mockSerializationWriter.Object); + SerializationWriterFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockSerializationWriterFactory.Object; + + var result = SerializationHelpers.SerializeAsString(_jsonContentType, new TestEntity() + { + Id = "123" + }); + + Assert.Equal("{'id':'123'}", result); + + mockSerializationWriterFactory.Verify(x => x.GetSerializationWriter(It.IsAny()), Times.Once); + mockSerializationWriter.Verify(x => x.WriteObjectValue(It.IsAny(), It.IsAny()), Times.Once); + mockSerializationWriter.Verify(x => x.GetSerializedContent(), Times.Once); + } + [Fact] + public void SerializesObjectCollection() + { + var mockSerializationWriter = new Mock(); + mockSerializationWriter.Setup(x => x.GetSerializedContent()).Returns(new MemoryStream(UTF8Encoding.UTF8.GetBytes("[{'id':'123'}]"))); + var mockSerializationWriterFactory = new Mock(); + mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny())).Returns(mockSerializationWriter.Object); + SerializationWriterFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockSerializationWriterFactory.Object; + + var result = SerializationHelpers.SerializeAsString(_jsonContentType, new List { + new() + { + Id = "123" + } + }); + + Assert.Equal("[{'id':'123'}]", result); + + mockSerializationWriterFactory.Verify(x => x.GetSerializationWriter(It.IsAny()), Times.Once); + mockSerializationWriter.Verify(x => x.WriteCollectionOfObjectValues(It.IsAny(), It.IsAny>()), Times.Once); + mockSerializationWriter.Verify(x => x.GetSerializedContent(), Times.Once); + } +} \ No newline at end of file diff --git a/src/serialization/JsonSerializationHelpers.cs b/src/serialization/JsonSerializationHelpers.cs new file mode 100644 index 00000000..96c7913c --- /dev/null +++ b/src/serialization/JsonSerializationHelpers.cs @@ -0,0 +1,55 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ + +using System.Collections.Generic; +using System.IO; +#if NET5_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + +namespace Microsoft.Kiota.Abstractions.Serialization; + +/// +/// Set of helper methods for JSON serialization +/// +public static class JsonSerializationHelpers +{ + private const string _jsonContentType = "application/json"; + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// The object to serialize. + /// The serialized representation as a stream. + public static Stream SerializeAsStream(T value) where T : IParsable + => SerializationHelpers.SerializeAsStream(_jsonContentType, value); + + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// The object to serialize. + /// The serialized representation as a string. + public static string SerializeAsString(T value) where T : IParsable + => SerializationHelpers.SerializeAsString(_jsonContentType, value); + + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// The object to serialize. + /// The serialized representation as a stream. + public static Stream SerializeAsStream(IEnumerable value) where T : IParsable + => SerializationHelpers.SerializeAsStream(_jsonContentType, value); + + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// The object to serialize. + /// The serialized representation as a string. + public static string SerializeAsString(IEnumerable value) where T : IParsable + => SerializationHelpers.SerializeAsString(_jsonContentType, value); + +} \ No newline at end of file diff --git a/src/serialization/SerializationHelpers.cs b/src/serialization/SerializationHelpers.cs new file mode 100644 index 00000000..2749ed5d --- /dev/null +++ b/src/serialization/SerializationHelpers.cs @@ -0,0 +1,81 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.IO; +#if NET5_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + + +namespace Microsoft.Kiota.Abstractions.Serialization; + +/// +/// Set of helper methods for serialization +/// +public static class SerializationHelpers +{ + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// Content type to serialize the object to + /// The object to serialize. + /// The serialized representation as a stream. + public static Stream SerializeAsStream(string contentType, T value) where T : IParsable + { + using var writer = GetSerializationWriter(contentType, value); + writer.WriteObjectValue(string.Empty, value); + return writer.GetSerializedContent(); + } + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// Content type to serialize the object to + /// The object to serialize. + /// The serialized representation as a string. + public static string SerializeAsString(string contentType, T value) where T : IParsable + { + using var stream = SerializeAsStream(contentType, value); + return GetStringFromStream(stream); + } + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// Content type to serialize the object to + /// The object to serialize. + /// The serialized representation as a stream. + public static Stream SerializeAsStream(string contentType, IEnumerable value) where T : IParsable + { + using var writer = GetSerializationWriter(contentType, value); + writer.WriteCollectionOfObjectValues(string.Empty, value); + return writer.GetSerializedContent(); + } + /// + /// Serializes the given object into a string based on the content type. + /// + /// Type of the object to serialize + /// Content type to serialize the object to + /// The object to serialize. + /// The serialized representation as a string. + public static string SerializeAsString(string contentType, IEnumerable value) where T : IParsable + { + using var stream = SerializeAsStream(contentType, value); + return GetStringFromStream(stream); + } + private static string GetStringFromStream(Stream stream) + { + using var reader = new StreamReader(stream); + return reader.ReadToEndAsync().ConfigureAwait(false).GetAwaiter().GetResult(); // so the asp.net projects don't get an error + } + private static ISerializationWriter GetSerializationWriter(string contentType, object value) + { + if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); + if(value == null) throw new ArgumentNullException(nameof(value)); + return SerializationWriterFactoryRegistry.DefaultInstance.GetSerializationWriter(contentType); + } +} \ No newline at end of file From e0b5c36dedeff53cc41d1d7b0942713b3b1e471d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 30 Oct 2023 15:47:14 -0400 Subject: [PATCH 09/11] - code linting Signed-off-by: Vincent Biret --- src/serialization/DeserializationHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serialization/DeserializationHelpers.cs b/src/serialization/DeserializationHelpers.cs index 74ee97c1..3cd2655d 100644 --- a/src/serialization/DeserializationHelpers.cs +++ b/src/serialization/DeserializationHelpers.cs @@ -72,7 +72,7 @@ private static ParsableFactory GetFactoryFromType() where T : IParsable #endif { var type = typeof(T); - var factoryMethod = type.GetMethods().FirstOrDefault(static x => x.IsStatic && "CreateFromDiscriminatorValue".Equals(x.Name, StringComparison.OrdinalIgnoreCase)) ?? + var factoryMethod = Array.Find(type.GetMethods(), static x => x.IsStatic && "CreateFromDiscriminatorValue".Equals(x.Name, StringComparison.OrdinalIgnoreCase)) ?? throw new InvalidOperationException($"No factory method found for type {type.Name}"); return (ParsableFactory)factoryMethod.CreateDelegate(typeof(ParsableFactory)); } From 6752388724c7fe9a27b4438e9815cd6f6a6a2173 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 31 Oct 2023 12:34:39 -0400 Subject: [PATCH 10/11] - applies feedback from issue discussion --- .../DeserializationHelpersTests.cs | 22 +++++++++---------- .../SerializationHelpersTests.cs | 12 +++++----- ...=> KiotaJsonSerializer.Deserialization.cs} | 18 +++++++-------- ...s => KiotaJsonSerializer.Serialization.cs} | 14 +++++------- ....cs => KiotaSerializer.Deserialization.cs} | 6 +---- ...rs.cs => KiotaSerializer.Serialization.cs} | 2 +- 6 files changed, 33 insertions(+), 41 deletions(-) rename src/serialization/{JsonDeserializationHelpers.cs => KiotaJsonSerializer.Deserialization.cs} (84%) rename src/serialization/{JsonSerializationHelpers.cs => KiotaJsonSerializer.Serialization.cs} (81%) rename src/serialization/{DeserializationHelpers.cs => KiotaSerializer.Deserialization.cs} (98%) rename src/serialization/{SerializationHelpers.cs => KiotaSerializer.Serialization.cs} (98%) diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/DeserializationHelpersTests.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/DeserializationHelpersTests.cs index 7cb78fb6..272d1f4a 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Serialization/DeserializationHelpersTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/DeserializationHelpersTests.cs @@ -14,20 +14,20 @@ public class DeserializationHelpersTests [Fact] public void DefensiveObject() { - Assert.Throws(() => DeserializationHelpers.Deserialize(null, (Stream)null, null)); - Assert.Throws(() => DeserializationHelpers.Deserialize(_jsonContentType, (Stream)null, null)); + Assert.Throws(() => KiotaSerializer.Deserialize(null, (Stream)null, null)); + Assert.Throws(() => KiotaSerializer.Deserialize(_jsonContentType, (Stream)null, null)); using var stream = new MemoryStream(); - Assert.Throws(() => DeserializationHelpers.Deserialize(_jsonContentType, stream, null)); - Assert.Throws(() => DeserializationHelpers.Deserialize(_jsonContentType, "", null)); + Assert.Throws(() => KiotaSerializer.Deserialize(_jsonContentType, stream, null)); + Assert.Throws(() => KiotaSerializer.Deserialize(_jsonContentType, "", null)); } [Fact] public void DefensiveObjectCollection() { - Assert.Throws(() => DeserializationHelpers.DeserializeCollection(null, (Stream)null, null)); - Assert.Throws(() => DeserializationHelpers.DeserializeCollection(_jsonContentType, (Stream)null, null)); + Assert.Throws(() => KiotaSerializer.DeserializeCollection(null, (Stream)null, null)); + Assert.Throws(() => KiotaSerializer.DeserializeCollection(_jsonContentType, (Stream)null, null)); using var stream = new MemoryStream(); - Assert.Throws(() => DeserializationHelpers.DeserializeCollection(_jsonContentType, stream, null)); - Assert.Throws(() => DeserializationHelpers.DeserializeCollection(_jsonContentType, "", null)); + Assert.Throws(() => KiotaSerializer.DeserializeCollection(_jsonContentType, stream, null)); + Assert.Throws(() => KiotaSerializer.DeserializeCollection(_jsonContentType, "", null)); } [Fact] public void DeserializesObjectWithoutReflection() @@ -43,7 +43,7 @@ public void DeserializesObjectWithoutReflection() mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; - var result = DeserializationHelpers.Deserialize(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); + var result = KiotaSerializer.Deserialize(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); Assert.NotNull(result); } @@ -61,7 +61,7 @@ public void DeserializesObjectWithReflection() mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; - var result = DeserializationHelpers.Deserialize(_jsonContentType, strValue); + var result = KiotaSerializer.Deserialize(_jsonContentType, strValue); Assert.NotNull(result); } @@ -81,7 +81,7 @@ public void DeserializesCollectionOfObject() mockJsonParseNodeFactory.Setup(x => x.ValidContentType).Returns(_jsonContentType); ParseNodeFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockJsonParseNodeFactory.Object; - var result = DeserializationHelpers.DeserializeCollection(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); + var result = KiotaSerializer.DeserializeCollection(_jsonContentType, strValue, TestEntity.CreateFromDiscriminatorValue); Assert.NotNull(result); Assert.Single(result); diff --git a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs index 4d72605e..79d8e2a9 100644 --- a/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs +++ b/Microsoft.Kiota.Abstractions.Tests/Serialization/SerializationHelpersTests.cs @@ -15,14 +15,14 @@ public class SerializationHelpersTests [Fact] public void DefensiveObject() { - Assert.Throws(() => SerializationHelpers.SerializeAsStream(null, (TestEntity)null)); - Assert.Throws(() => SerializationHelpers.SerializeAsStream(_jsonContentType, (TestEntity)null)); + Assert.Throws(() => KiotaSerializer.SerializeAsStream(null, (TestEntity)null)); + Assert.Throws(() => KiotaSerializer.SerializeAsStream(_jsonContentType, (TestEntity)null)); } [Fact] public void DefensiveObjectCollection() { - Assert.Throws(() => SerializationHelpers.SerializeAsStream(null, (IEnumerable)null)); - Assert.Throws(() => SerializationHelpers.SerializeAsStream(_jsonContentType, (IEnumerable)null)); + Assert.Throws(() => KiotaSerializer.SerializeAsStream(null, (IEnumerable)null)); + Assert.Throws(() => KiotaSerializer.SerializeAsStream(_jsonContentType, (IEnumerable)null)); } [Fact] public void SerializesObject() @@ -33,7 +33,7 @@ public void SerializesObject() mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny())).Returns(mockSerializationWriter.Object); SerializationWriterFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockSerializationWriterFactory.Object; - var result = SerializationHelpers.SerializeAsString(_jsonContentType, new TestEntity() + var result = KiotaSerializer.SerializeAsString(_jsonContentType, new TestEntity() { Id = "123" }); @@ -53,7 +53,7 @@ public void SerializesObjectCollection() mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny())).Returns(mockSerializationWriter.Object); SerializationWriterFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockSerializationWriterFactory.Object; - var result = SerializationHelpers.SerializeAsString(_jsonContentType, new List { + var result = KiotaSerializer.SerializeAsString(_jsonContentType, new List { new() { Id = "123" diff --git a/src/serialization/JsonDeserializationHelpers.cs b/src/serialization/KiotaJsonSerializer.Deserialization.cs similarity index 84% rename from src/serialization/JsonDeserializationHelpers.cs rename to src/serialization/KiotaJsonSerializer.Deserialization.cs index 958b699c..27ac6817 100644 --- a/src/serialization/JsonDeserializationHelpers.cs +++ b/src/serialization/KiotaJsonSerializer.Deserialization.cs @@ -13,7 +13,7 @@ namespace Microsoft.Kiota.Abstractions.Serialization; /// /// Set of helper methods for JSON serialization /// -public static class JsonDeserializationHelpers +public static partial class KiotaJsonSerializer { private const string _jsonContentType = "application/json"; /// @@ -22,14 +22,14 @@ public static class JsonDeserializationHelpers /// The factory to create the object. /// The serialized representation of the object. public static T? Deserialize(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable - => DeserializationHelpers.Deserialize(_jsonContentType, serializedRepresentation, parsableFactory); + => KiotaSerializer.Deserialize(_jsonContentType, serializedRepresentation, parsableFactory); /// /// Deserializes the given stream into an object. /// /// The stream to deserialize. /// The factory to create the object. public static T? Deserialize(Stream stream, ParsableFactory parsableFactory) where T : IParsable - => DeserializationHelpers.Deserialize(_jsonContentType, stream, parsableFactory); + => KiotaSerializer.Deserialize(_jsonContentType, stream, parsableFactory); /// /// Deserializes the given stream into an object. /// @@ -39,7 +39,7 @@ public static class JsonDeserializationHelpers #else public static T? Deserialize(Stream stream) where T : IParsable #endif - => DeserializationHelpers.Deserialize(_jsonContentType, stream); + => KiotaSerializer.Deserialize(_jsonContentType, stream); /// /// Deserializes the given stream into an object. /// @@ -49,21 +49,21 @@ public static class JsonDeserializationHelpers #else public static T? Deserialize(string serializedRepresentation) where T : IParsable #endif - => DeserializationHelpers.Deserialize(_jsonContentType, serializedRepresentation); + => KiotaSerializer.Deserialize(_jsonContentType, serializedRepresentation); /// /// Deserializes the given stream into a collection of objects based on the content type. /// /// The stream to deserialize. /// The factory to create the object. public static IEnumerable DeserializeCollection(Stream stream, ParsableFactory parsableFactory) where T : IParsable - => DeserializationHelpers.DeserializeCollection(_jsonContentType, stream, parsableFactory); + => KiotaSerializer.DeserializeCollection(_jsonContentType, stream, parsableFactory); /// /// Deserializes the given stream into a collection of objects based on the content type. /// /// The serialized representation of the objects. /// The factory to create the object. public static IEnumerable DeserializeCollection(string serializedRepresentation, ParsableFactory parsableFactory) where T : IParsable - => DeserializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation, parsableFactory); + => KiotaSerializer.DeserializeCollection(_jsonContentType, serializedRepresentation, parsableFactory); /// /// Deserializes the given stream into a collection of objects based on the content type. /// @@ -73,7 +73,7 @@ public static IEnumerable DeserializeCollection(string serializedRepresent #else public static IEnumerable DeserializeCollection(Stream stream) where T : IParsable #endif - => DeserializationHelpers.DeserializeCollection(_jsonContentType, stream); + => KiotaSerializer.DeserializeCollection(_jsonContentType, stream); /// /// Deserializes the given stream into a collection of objects based on the content type. /// @@ -83,5 +83,5 @@ public static IEnumerable DeserializeCollection(Stream stream) where T : I #else public static IEnumerable DeserializeCollection(string serializedRepresentation) where T : IParsable #endif - => DeserializationHelpers.DeserializeCollection(_jsonContentType, serializedRepresentation); + => KiotaSerializer.DeserializeCollection(_jsonContentType, serializedRepresentation); } \ No newline at end of file diff --git a/src/serialization/JsonSerializationHelpers.cs b/src/serialization/KiotaJsonSerializer.Serialization.cs similarity index 81% rename from src/serialization/JsonSerializationHelpers.cs rename to src/serialization/KiotaJsonSerializer.Serialization.cs index 96c7913c..aa87f420 100644 --- a/src/serialization/JsonSerializationHelpers.cs +++ b/src/serialization/KiotaJsonSerializer.Serialization.cs @@ -10,12 +10,8 @@ namespace Microsoft.Kiota.Abstractions.Serialization; -/// -/// Set of helper methods for JSON serialization -/// -public static class JsonSerializationHelpers +public static partial class KiotaJsonSerializer { - private const string _jsonContentType = "application/json"; /// /// Serializes the given object into a string based on the content type. /// @@ -23,7 +19,7 @@ public static class JsonSerializationHelpers /// The object to serialize. /// The serialized representation as a stream. public static Stream SerializeAsStream(T value) where T : IParsable - => SerializationHelpers.SerializeAsStream(_jsonContentType, value); + => KiotaSerializer.SerializeAsStream(_jsonContentType, value); /// /// Serializes the given object into a string based on the content type. @@ -32,7 +28,7 @@ public static Stream SerializeAsStream(T value) where T : IParsable /// The object to serialize. /// The serialized representation as a string. public static string SerializeAsString(T value) where T : IParsable - => SerializationHelpers.SerializeAsString(_jsonContentType, value); + => KiotaSerializer.SerializeAsString(_jsonContentType, value); /// /// Serializes the given object into a string based on the content type. @@ -41,7 +37,7 @@ public static string SerializeAsString(T value) where T : IParsable /// The object to serialize. /// The serialized representation as a stream. public static Stream SerializeAsStream(IEnumerable value) where T : IParsable - => SerializationHelpers.SerializeAsStream(_jsonContentType, value); + => KiotaSerializer.SerializeAsStream(_jsonContentType, value); /// /// Serializes the given object into a string based on the content type. @@ -50,6 +46,6 @@ public static Stream SerializeAsStream(IEnumerable value) where T : IParsa /// The object to serialize. /// The serialized representation as a string. public static string SerializeAsString(IEnumerable value) where T : IParsable - => SerializationHelpers.SerializeAsString(_jsonContentType, value); + => KiotaSerializer.SerializeAsString(_jsonContentType, value); } \ No newline at end of file diff --git a/src/serialization/DeserializationHelpers.cs b/src/serialization/KiotaSerializer.Deserialization.cs similarity index 98% rename from src/serialization/DeserializationHelpers.cs rename to src/serialization/KiotaSerializer.Deserialization.cs index 3cd2655d..5756b08c 100644 --- a/src/serialization/DeserializationHelpers.cs +++ b/src/serialization/KiotaSerializer.Deserialization.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; #if NET5_0_OR_GREATER using System.Diagnostics.CodeAnalysis; @@ -14,10 +13,7 @@ namespace Microsoft.Kiota.Abstractions.Serialization; -/// -/// Set of helper methods for serialization -/// -public static class DeserializationHelpers +public static partial class KiotaSerializer { /// /// Deserializes the given stream into an object based on the content type. diff --git a/src/serialization/SerializationHelpers.cs b/src/serialization/KiotaSerializer.Serialization.cs similarity index 98% rename from src/serialization/SerializationHelpers.cs rename to src/serialization/KiotaSerializer.Serialization.cs index 2749ed5d..7abbd99b 100644 --- a/src/serialization/SerializationHelpers.cs +++ b/src/serialization/KiotaSerializer.Serialization.cs @@ -15,7 +15,7 @@ namespace Microsoft.Kiota.Abstractions.Serialization; /// /// Set of helper methods for serialization /// -public static class SerializationHelpers +public static partial class KiotaSerializer { /// /// Serializes the given object into a string based on the content type. From 7a0c44417670b9f634ec1c4d4c0639eb4199ab54 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 31 Oct 2023 12:51:00 -0400 Subject: [PATCH 11/11] - bumps version number --- CHANGELOG.md | 6 ++++++ src/Microsoft.Kiota.Abstractions.csproj | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf15f234..c2f8072a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.6.0] - 2023-10-31 + +### Added + +- Added helper methods to facilitate serialization and deserialization of models. [microsoft/kiota#3406](https://github.com/microsoft/kiota/issues/3406) + ## [1.5.0] - 2023-10-19 ### Added diff --git a/src/Microsoft.Kiota.Abstractions.csproj b/src/Microsoft.Kiota.Abstractions.csproj index bdba8831..aea567dd 100644 --- a/src/Microsoft.Kiota.Abstractions.csproj +++ b/src/Microsoft.Kiota.Abstractions.csproj @@ -14,7 +14,7 @@ https://aka.ms/kiota/docs true true - 1.5.0 + 1.6.0 true false