diff --git a/src/abstractions/serialization/KiotaJsonSerializer.Serialization.cs b/src/abstractions/serialization/KiotaJsonSerializer.Serialization.cs
index ac5141cf..087e7e3e 100644
--- a/src/abstractions/serialization/KiotaJsonSerializer.Serialization.cs
+++ b/src/abstractions/serialization/KiotaJsonSerializer.Serialization.cs
@@ -17,6 +17,17 @@ namespace Microsoft.Kiota.Abstractions.Serialization;
public static partial class KiotaJsonSerializer
{
+ ///
+ /// 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.
+ [Obsolete("This method is obsolete, use the extension methods in Microsoft.Kiota.Serialization.Json.IParsableExtensions instead")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static Stream SerializeAsStream(T value) where T : IParsable
+ => KiotaSerializer.SerializeAsStream(_jsonContentType, value);
+
///
/// Serializes the given object into a string based on the content type.
///
@@ -72,6 +83,4 @@ public static string SerializeAsString(IEnumerable value) where T : IParsa
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task SerializeAsStringAsync(IEnumerable value, CancellationToken cancellationToken) where T : IParsable =>
KiotaSerializer.SerializeAsStringAsync(_jsonContentType, value, true, cancellationToken);
-
-
-}
\ No newline at end of file
+}
diff --git a/src/abstractions/serialization/SerializationWriterFactoryRegistry.cs b/src/abstractions/serialization/SerializationWriterFactoryRegistry.cs
index bc71d7fd..b4f65d1e 100644
--- a/src/abstractions/serialization/SerializationWriterFactoryRegistry.cs
+++ b/src/abstractions/serialization/SerializationWriterFactoryRegistry.cs
@@ -26,30 +26,19 @@ public string ValidContentType
/// Default singleton instance of the registry to be used when registering new factories that should be available by default.
///
public static readonly SerializationWriterFactoryRegistry DefaultInstance = new();
+
///
/// List of factories that are registered by content type.
///
public ConcurrentDictionary ContentTypeAssociatedFactories { get; set; } = new();
+
///
/// Get the relevant instance for the given content type
///
/// The content type in use
/// A instance to parse the content
public ISerializationWriter GetSerializationWriter(string contentType)
- {
- if(string.IsNullOrEmpty(contentType))
- throw new ArgumentNullException(nameof(contentType));
-
- var vendorSpecificContentType = contentType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0];
- if(ContentTypeAssociatedFactories.TryGetValue(vendorSpecificContentType, out var vendorFactory))
- return vendorFactory.GetSerializationWriter(vendorSpecificContentType);
-
- var cleanedContentType = ParseNodeFactoryRegistry.contentTypeVendorCleanupRegex.Replace(vendorSpecificContentType, string.Empty);
- if(ContentTypeAssociatedFactories.TryGetValue(cleanedContentType, out var factory))
- return factory.GetSerializationWriter(cleanedContentType);
-
- throw new InvalidOperationException($"Content type {cleanedContentType} does not have a factory registered to be parsed");
- }
+ => GetSerializationWriter(contentType, true);
///
/// Get the relevant instance for the given content type
@@ -59,35 +48,39 @@ public ISerializationWriter GetSerializationWriter(string contentType)
/// A instance to parse the content
public ISerializationWriter GetSerializationWriter(string contentType, bool serializeOnlyChangedValues)
{
- if(serializeOnlyChangedValues)
- return GetSerializationWriter(contentType);
-
- var factory = GetSerializationWriterFactory(contentType);
- if(factory is Store.BackingStoreSerializationWriterProxyFactory backingStoreFactory)
- return backingStoreFactory.GetSerializationWriter(contentType, false);
+ var factory = GetSerializationWriterFactory(contentType, out string actualContentType);
+ if(!serializeOnlyChangedValues && factory is Store.BackingStoreSerializationWriterProxyFactory backingStoreFactory)
+ return backingStoreFactory.GetSerializationWriter(actualContentType, false);
- return factory.GetSerializationWriter(contentType);
+ return factory.GetSerializationWriter(actualContentType);
}
///
/// Get the relevant instance for the given content type
///
/// The content type in use
+ /// The content type where a writer factory is found for
///
///
///
- private ISerializationWriterFactory GetSerializationWriterFactory(string contentType)
+ private ISerializationWriterFactory GetSerializationWriterFactory(string contentType, out string actualContentType)
{
if(string.IsNullOrEmpty(contentType))
throw new ArgumentNullException(nameof(contentType));
var vendorSpecificContentType = contentType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0];
if(ContentTypeAssociatedFactories.TryGetValue(vendorSpecificContentType, out var vendorFactory))
+ {
+ actualContentType = vendorSpecificContentType;
return vendorFactory;
+ }
var cleanedContentType = ParseNodeFactoryRegistry.contentTypeVendorCleanupRegex.Replace(vendorSpecificContentType, string.Empty);
if(ContentTypeAssociatedFactories.TryGetValue(cleanedContentType, out var factory))
+ {
+ actualContentType = cleanedContentType;
return factory;
+ }
throw new InvalidOperationException($"Content type {cleanedContentType} does not have a factory registered to be parsed");
}
diff --git a/src/abstractions/serialization/SerializationWriterProxyFactory.cs b/src/abstractions/serialization/SerializationWriterProxyFactory.cs
index 0e518534..d5a59786 100644
--- a/src/abstractions/serialization/SerializationWriterProxyFactory.cs
+++ b/src/abstractions/serialization/SerializationWriterProxyFactory.cs
@@ -14,28 +14,28 @@ public class SerializationWriterProxyFactory : ISerializationWriterFactory
///
/// The valid content type for the
///
- public string ValidContentType { get { return _concrete.ValidContentType; } }
+ public string ValidContentType { get { return ProxiedSerializationWriterFactory.ValidContentType; } }
///
- /// The concrete factory to wrap.
+ /// The factory that is being proxied.
///
- protected readonly ISerializationWriterFactory _concrete;
+ protected readonly ISerializationWriterFactory ProxiedSerializationWriterFactory;
private readonly Action _onBefore;
private readonly Action _onAfter;
private readonly Action _onStartSerialization;
///
/// Creates a new proxy factory that wraps the specified concrete factory while composing the before and after callbacks.
///
- /// The concrete factory to wrap.
+ /// The concrete factory to wrap.
/// The callback to invoke before the serialization of any model object.
/// The callback to invoke after the serialization of any model object.
/// The callback to invoke when serialization of the entire model has started.
- public SerializationWriterProxyFactory(ISerializationWriterFactory concrete,
+ public SerializationWriterProxyFactory(ISerializationWriterFactory factoryToWrap,
Action onBeforeSerialization,
Action onAfterSerialization,
Action onStartSerialization)
{
- _concrete = concrete ?? throw new ArgumentNullException(nameof(concrete));
+ ProxiedSerializationWriterFactory = factoryToWrap ?? throw new ArgumentNullException(nameof(factoryToWrap));
_onBefore = onBeforeSerialization;
_onAfter = onAfterSerialization;
_onStartSerialization = onStartSerialization;
@@ -47,7 +47,7 @@ public SerializationWriterProxyFactory(ISerializationWriterFactory concrete,
/// A new instance for the given content type.
public ISerializationWriter GetSerializationWriter(string contentType)
{
- var writer = _concrete.GetSerializationWriter(contentType);
+ var writer = ProxiedSerializationWriterFactory.GetSerializationWriter(contentType);
var originalBefore = writer.OnBeforeObjectSerialization;
var originalAfter = writer.OnAfterObjectSerialization;
var originalStart = writer.OnStartObjectSerialization;
diff --git a/src/abstractions/store/BackingStoreSerializationWriterProxyFactory.cs b/src/abstractions/store/BackingStoreSerializationWriterProxyFactory.cs
index 79ad1cc9..87915a7c 100644
--- a/src/abstractions/store/BackingStoreSerializationWriterProxyFactory.cs
+++ b/src/abstractions/store/BackingStoreSerializationWriterProxyFactory.cs
@@ -42,14 +42,14 @@ public BackingStoreSerializationWriterProxyFactory(ISerializationWriterFactory c
/// Get the serialization writer for the given content type.
///
/// The content type for which a serialization writer should be created.
- /// By default a backing store is used, and you'll only get changed properties
+ /// By default, a backing store is used, and you'll only get changed properties
///
public ISerializationWriter GetSerializationWriter(string contentType, bool serializeOnlyChangedValues)
{
if(serializeOnlyChangedValues)
return base.GetSerializationWriter(contentType);
- return _concrete.GetSerializationWriter(contentType);
+ return ProxiedSerializationWriterFactory.GetSerializationWriter(contentType);
}
}
}
diff --git a/tests/serialization/json/IParsableExtensionsTests.cs b/tests/serialization/json/IParsableExtensionsTests.cs
new file mode 100644
index 00000000..71db6a41
--- /dev/null
+++ b/tests/serialization/json/IParsableExtensionsTests.cs
@@ -0,0 +1,99 @@
+using System.IO;
+using Microsoft.Kiota.Abstractions.Serialization;
+using Microsoft.Kiota.Abstractions.Store;
+using Microsoft.Kiota.Serialization.Json.Tests.Mocks;
+using Xunit;
+
+namespace Microsoft.Kiota.Serialization.Json.Tests
+{
+ public class IParsableExtensionsTests
+ {
+ private const string _jsonContentType = "application/json";
+ private readonly SerializationWriterFactoryRegistry _serializationWriterFactoryRegistry;
+
+ public IParsableExtensionsTests()
+ {
+ _serializationWriterFactoryRegistry = new SerializationWriterFactoryRegistry();
+ _serializationWriterFactoryRegistry.ContentTypeAssociatedFactories.TryAdd(_jsonContentType, new BackingStoreSerializationWriterProxyFactory(new JsonSerializationWriterFactory()));
+ }
+
+ [Theory]
+ [InlineData(null)]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void GetSerializationWriter_RetunsJsonSerializationWriter(bool? serializeOnlyChangedValues)
+ {
+ // Arrange
+
+ // Act
+ using var writer = serializeOnlyChangedValues.HasValue
+ ? _serializationWriterFactoryRegistry.GetSerializationWriter(_jsonContentType, serializeOnlyChangedValues.Value)
+ : _serializationWriterFactoryRegistry.GetSerializationWriter(_jsonContentType);
+
+ // Assert
+ Assert.NotNull(writer);
+ Assert.IsType(writer);
+ }
+
+ [Fact]
+ public void GetSerializationWriterSerializedChangedTrue_RetunsEmptyJson()
+ {
+ // Arrange
+ var testUser = new BackedTestEntity { Id = "1", Name = "testUser" };
+ testUser.BackingStore.InitializationCompleted = true;
+ using var writer = _serializationWriterFactoryRegistry.GetSerializationWriter(_jsonContentType, true);
+
+ // Act
+ writer.WriteObjectValue(null, testUser);
+ using var stream = writer.GetSerializedContent();
+ var serializedContent = GetStringFromStream(stream);
+
+ // Assert
+ Assert.NotNull(serializedContent);
+ Assert.Equal("{}", serializedContent);
+ }
+
+ [Fact]
+ public void GetSerializationWriterSerializedChangedTrue_ChangedName_ReturnsJustName()
+ {
+ // Arrange
+ var testUser = new BackedTestEntity { Id = "1", Name = "testUser" };
+ testUser.BackingStore.InitializationCompleted = true;
+ testUser.Name = "Stephan";
+ using var writer = _serializationWriterFactoryRegistry.GetSerializationWriter(_jsonContentType, true);
+
+ // Act
+ writer.WriteObjectValue(null, testUser);
+ using var stream = writer.GetSerializedContent();
+ var serializedContent = GetStringFromStream(stream);
+
+ // Assert
+ Assert.NotNull(serializedContent);
+ Assert.Equal("{\"name\":\"Stephan\"}", serializedContent);
+ }
+
+ [Fact]
+ public void GetSerializationWriterSerializedChangedFalse_SerializesEntireObject()
+ {
+ // Arrange
+ var testUser = new BackedTestEntity { Id = "1", Name = "testUser" };
+ testUser.BackingStore.InitializationCompleted = true;
+ using var writer = _serializationWriterFactoryRegistry.GetSerializationWriter(_jsonContentType, false);
+
+ // Act
+ writer.WriteObjectValue(null, testUser);
+ using var stream = writer.GetSerializedContent();
+ var serializedContent = GetStringFromStream(stream);
+
+ // Assert
+ Assert.NotNull(serializedContent);
+ Assert.Equal("{\"id\":\"1\",\"name\":\"testUser\"}", serializedContent);
+ }
+
+ private static string GetStringFromStream(Stream stream)
+ {
+ using var reader = new StreamReader(stream);
+ return reader.ReadToEnd();
+ }
+ }
+}
diff --git a/tests/serialization/json/Mocks/BackedTestEntity.cs b/tests/serialization/json/Mocks/BackedTestEntity.cs
new file mode 100644
index 00000000..6ff41b8b
--- /dev/null
+++ b/tests/serialization/json/Mocks/BackedTestEntity.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Kiota.Abstractions.Serialization;
+using Microsoft.Kiota.Abstractions.Store;
+
+namespace Microsoft.Kiota.Serialization.Json.Tests.Mocks
+{
+ public class BackedTestEntity : IParsable, IBackedModel
+ {
+ public BackedTestEntity()
+ {
+ BackingStore = new InMemoryBackingStore();
+ }
+
+ public IBackingStore BackingStore { get; private set; }
+
+ public string Id
+ {
+ get { return BackingStore?.Get("id"); }
+ set { BackingStore?.Set("id", value); }
+ }
+ public string Name
+ {
+ get { return BackingStore?.Get("name"); }
+ set { BackingStore?.Set("name", value); }
+ }
+
+ public IDictionary> GetFieldDeserializers() =>
+ new Dictionary> {
+ { "id", n => { Id = n.GetStringValue(); } },
+ { "name", n => { Name = n.GetStringValue(); } },
+ };
+ public void Serialize(ISerializationWriter writer)
+ {
+ _ = writer ?? throw new ArgumentNullException(nameof(writer));
+ writer.WriteStringValue("id", Id);
+ writer.WriteStringValue("name", Name);
+ }
+ }
+}