Skip to content

Commit

Permalink
- adds serialization helpers
Browse files Browse the repository at this point in the history
Signed-off-by: Vincent Biret <[email protected]>
  • Loading branch information
baywet committed Oct 30, 2023
1 parent 5d429e7 commit 0b75243
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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<ArgumentNullException>(() => SerializationHelpers.SerializeAsStream(null, (TestEntity)null));
Assert.Throws<ArgumentNullException>(() => SerializationHelpers.SerializeAsStream(_jsonContentType, (TestEntity)null));
}
[Fact]
public void DefensiveObjectCollection()
{
Assert.Throws<ArgumentNullException>(() => SerializationHelpers.SerializeAsStream(null, (IEnumerable<TestEntity>)null));
Assert.Throws<ArgumentNullException>(() => SerializationHelpers.SerializeAsStream(_jsonContentType, (IEnumerable<TestEntity>)null));
}
[Fact]
public void SerializesObject()
{
var mockSerializationWriter = new Mock<ISerializationWriter>();
mockSerializationWriter.Setup(x => x.GetSerializedContent()).Returns(new MemoryStream(UTF8Encoding.UTF8.GetBytes("{'id':'123'}")));
var mockSerializationWriterFactory = new Mock<ISerializationWriterFactory>();
mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny<string>())).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<string>()), Times.Once);
mockSerializationWriter.Verify(x => x.WriteObjectValue(It.IsAny<string>(), It.IsAny<TestEntity>()), Times.Once);
mockSerializationWriter.Verify(x => x.GetSerializedContent(), Times.Once);
}
[Fact]
public void SerializesObjectCollection()
{
var mockSerializationWriter = new Mock<ISerializationWriter>();
mockSerializationWriter.Setup(x => x.GetSerializedContent()).Returns(new MemoryStream(UTF8Encoding.UTF8.GetBytes("[{'id':'123'}]")));
var mockSerializationWriterFactory = new Mock<ISerializationWriterFactory>();
mockSerializationWriterFactory.Setup(x => x.GetSerializationWriter(It.IsAny<string>())).Returns(mockSerializationWriter.Object);
SerializationWriterFactoryRegistry.DefaultInstance.ContentTypeAssociatedFactories[_jsonContentType] = mockSerializationWriterFactory.Object;

var result = SerializationHelpers.SerializeAsString(_jsonContentType, new List<TestEntity> {
new()
{
Id = "123"
}
});

Assert.Equal("[{'id':'123'}]", result);

mockSerializationWriterFactory.Verify(x => x.GetSerializationWriter(It.IsAny<string>()), Times.Once);
mockSerializationWriter.Verify(x => x.WriteCollectionOfObjectValues(It.IsAny<string>(), It.IsAny<IEnumerable<TestEntity>>()), Times.Once);
mockSerializationWriter.Verify(x => x.GetSerializedContent(), Times.Once);
}
}
55 changes: 55 additions & 0 deletions src/serialization/JsonSerializationHelpers.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Set of helper methods for JSON serialization
/// </summary>
public static class JsonSerializationHelpers
{
private const string _jsonContentType = "application/json";
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a stream.</returns>
public static Stream SerializeAsStream<T>(T value) where T : IParsable

Check warning on line 25 in src/serialization/JsonSerializationHelpers.cs

View workflow job for this annotation

GitHub Actions / Build

All 'SerializeAsStream' method overloads should be adjacent. (https://rules.sonarsource.com/csharp/RSPEC-4136)
=> SerializationHelpers.SerializeAsStream(_jsonContentType, value);

/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
public static string SerializeAsString<T>(T value) where T : IParsable

Check warning on line 34 in src/serialization/JsonSerializationHelpers.cs

View workflow job for this annotation

GitHub Actions / Build

All 'SerializeAsString' method overloads should be adjacent. (https://rules.sonarsource.com/csharp/RSPEC-4136)
=> SerializationHelpers.SerializeAsString(_jsonContentType, value);

/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a stream.</returns>
public static Stream SerializeAsStream<T>(IEnumerable<T> value) where T : IParsable
=> SerializationHelpers.SerializeAsStream(_jsonContentType, value);

/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
public static string SerializeAsString<T>(IEnumerable<T> value) where T : IParsable
=> SerializationHelpers.SerializeAsString(_jsonContentType, value);

}
81 changes: 81 additions & 0 deletions src/serialization/SerializationHelpers.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Set of helper methods for serialization
/// </summary>
public static class SerializationHelpers
{
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a stream.</returns>
public static Stream SerializeAsStream<T>(string contentType, T value) where T : IParsable

Check warning on line 27 in src/serialization/SerializationHelpers.cs

View workflow job for this annotation

GitHub Actions / Build

All 'SerializeAsStream' method overloads should be adjacent. (https://rules.sonarsource.com/csharp/RSPEC-4136)
{
using var writer = GetSerializationWriter(contentType, value);
writer.WriteObjectValue(string.Empty, value);
return writer.GetSerializedContent();
}
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
public static string SerializeAsString<T>(string contentType, T value) where T : IParsable

Check warning on line 40 in src/serialization/SerializationHelpers.cs

View workflow job for this annotation

GitHub Actions / Build

All 'SerializeAsString' method overloads should be adjacent. (https://rules.sonarsource.com/csharp/RSPEC-4136)
{
using var stream = SerializeAsStream(contentType, value);
return GetStringFromStream(stream);
}
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a stream.</returns>
public static Stream SerializeAsStream<T>(string contentType, IEnumerable<T> value) where T : IParsable
{
using var writer = GetSerializationWriter(contentType, value);
writer.WriteCollectionOfObjectValues(string.Empty, value);
return writer.GetSerializedContent();
}
/// <summary>
/// Serializes the given object into a string based on the content type.
/// </summary>
/// <typeparam name="T">Type of the object to serialize</typeparam>
/// <param name="contentType">Content type to serialize the object to </param>
/// <param name="value">The object to serialize.</param>
/// <returns>The serialized representation as a string.</returns>
public static string SerializeAsString<T>(string contentType, IEnumerable<T> 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);
}
}

0 comments on commit 0b75243

Please sign in to comment.