Skip to content

Commit

Permalink
Improve serializer extensions (#153)
Browse files Browse the repository at this point in the history
I noticed that we forgot a `Deserialize` from `string` overload.

Besides that, I added the STJ shortcut path to the `SerializeToBytes`
extension methods.
  • Loading branch information
flobernd authored Jan 30, 2025
1 parent ec5f19d commit 32b2152
Showing 1 changed file with 73 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ public static byte[] SerializeToBytes<T>(
SerializationFormatting formatting = SerializationFormatting.None
)
{
if (serializer is SystemTextJsonSerializer stjSerializer)
{
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations.
return JsonSerializer.SerializeToUtf8Bytes(data, stjSerializer.GetJsonSerializerOptions(formatting));
}

memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
using var ms = memoryStreamFactory.Create();
serializer.Serialize(data, ms, formatting);
Expand Down Expand Up @@ -86,6 +92,12 @@ public static byte[] SerializeToBytes(
SerializationFormatting formatting = SerializationFormatting.None
)
{
if (serializer is SystemTextJsonSerializer stjSerializer)
{
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations.
return JsonSerializer.SerializeToUtf8Bytes(data, type, stjSerializer.GetJsonSerializerOptions(formatting));
}

memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
using var ms = memoryStreamFactory.Create();
serializer.Serialize(data, ms, formatting);
Expand Down Expand Up @@ -304,6 +316,65 @@ public static void Serialize(
#endif
}

/// <summary>
/// Extension method that deserializes from a UTF8 <see cref="string"/>.
/// </summary>
/// <typeparam name="T">The type of the data to be deserialized.</typeparam>
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
/// <param name="input">The source <see cref="string"/> that contains the JSON.</param>
/// <param name="memoryStreamFactory">
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
/// that yields memory streams backed by pooled byte arrays.
/// </param>
/// <returns>The deserialized data.</returns>
public static T? Deserialize<T>(
this Serializer serializer,
string input,
MemoryStreamFactory? memoryStreamFactory = null)
{
if (serializer is SystemTextJsonSerializer stjSerializer)
{
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
// deserialize straight from the span.
return JsonSerializer.Deserialize<T>(input, stjSerializer.GetJsonSerializerOptions());
}

memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
using var ms = memoryStreamFactory.Create(Encoding.UTF8.GetBytes(input));

return serializer.Deserialize<T>(ms);
}

/// <summary>
/// Extension method that deserializes from a <see cref="string"/>.
/// </summary>
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
/// <param name="input">The source <see cref="string"/> that contains the JSON.</param>
/// <param name="type">The type of the data to be deserialized.</param>
/// <param name="memoryStreamFactory">
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
/// that yields memory streams backed by pooled byte arrays.
/// </param>
/// <returns>The deserialized data.</returns>
public static object? Deserialize(
this Serializer serializer,
string input,
Type type,
MemoryStreamFactory? memoryStreamFactory = null)
{
if (serializer is SystemTextJsonSerializer stjSerializer)
{
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
// deserialize straight from the span.
return JsonSerializer.Deserialize(input, type, stjSerializer.GetJsonSerializerOptions());
}

memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
using var ms = memoryStreamFactory.Create(Encoding.UTF8.GetBytes(input));

return serializer.Deserialize(type, ms);
}

/// <summary>
/// Extension method that deserializes from a UTF8 <see cref="ReadOnlySpan{T}"/>.
/// </summary>
Expand Down Expand Up @@ -337,7 +408,7 @@ public static void Serialize(
/// Extension method that deserializes from a UTF8 <see cref="ReadOnlySpan{T}"/>.
/// </summary>
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON.</param>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON string.</param>
/// <param name="type">The type of the data to be deserialized.</param>
/// <param name="memoryStreamFactory">
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
Expand Down Expand Up @@ -396,7 +467,7 @@ public static void Serialize(
/// Extension method that deserializes from a UTF8 <see cref="ReadOnlySpan{T}"/>.
/// </summary>
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON.</param>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON string.</param>
/// <param name="type">The type of the data to be deserialized.</param>
/// <param name="memoryStreamFactory">
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
Expand Down

0 comments on commit 32b2152

Please sign in to comment.