diff --git a/sdk/core/Azure.Core/api/Azure.Core.net461.cs b/sdk/core/Azure.Core/api/Azure.Core.net461.cs index b0442e308807..d63632445e78 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net461.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net461.cs @@ -557,7 +557,9 @@ public JsonObjectSerializer(System.Text.Json.JsonSerializerOptions options) { } public override object? Deserialize(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } public override System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } public override void Serialize(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { } + public override System.BinaryData Serialize(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override System.Threading.Tasks.ValueTask SerializeAsync(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { throw null; } + public override System.Threading.Tasks.ValueTask SerializeAsync(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public abstract partial class ObjectSerializer { diff --git a/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs b/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs index 77b34996ff03..4e0f955a03af 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs @@ -557,7 +557,9 @@ public JsonObjectSerializer(System.Text.Json.JsonSerializerOptions options) { } public override object? Deserialize(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } public override System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } public override void Serialize(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { } + public override System.BinaryData Serialize(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override System.Threading.Tasks.ValueTask SerializeAsync(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { throw null; } + public override System.Threading.Tasks.ValueTask SerializeAsync(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public abstract partial class ObjectSerializer { diff --git a/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs b/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs index b0442e308807..d63632445e78 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs @@ -557,7 +557,9 @@ public JsonObjectSerializer(System.Text.Json.JsonSerializerOptions options) { } public override object? Deserialize(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } public override System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } public override void Serialize(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { } + public override System.BinaryData Serialize(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override System.Threading.Tasks.ValueTask SerializeAsync(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { throw null; } + public override System.Threading.Tasks.ValueTask SerializeAsync(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public abstract partial class ObjectSerializer { diff --git a/sdk/core/Azure.Core/src/Serialization/JsonObjectSerializer.cs b/sdk/core/Azure.Core/src/Serialization/JsonObjectSerializer.cs index 7a99ce919f78..d733dc90e104 100644 --- a/sdk/core/Azure.Core/src/Serialization/JsonObjectSerializer.cs +++ b/sdk/core/Azure.Core/src/Serialization/JsonObjectSerializer.cs @@ -67,6 +67,20 @@ public override async ValueTask SerializeAsync(Stream stream, object? value, Typ return JsonSerializer.DeserializeAsync(stream, returnType, _options, cancellationToken); } + /// + public override BinaryData Serialize(object? value, Type? inputType = default, CancellationToken cancellationToken = default) => + SerializeToBinaryDataInternal(value, inputType); + + /// + public override ValueTask SerializeAsync(object? value, Type? inputType = default, CancellationToken cancellationToken = default) => + new ValueTask(SerializeToBinaryDataInternal(value, inputType)); + + private BinaryData SerializeToBinaryDataInternal(object? value, Type? inputType) + { + byte[] bytes = JsonSerializer.SerializeToUtf8Bytes(value, inputType ?? value?.GetType() ?? typeof(object), _options); + return new BinaryData(bytes); + } + /// string? IMemberNameConverter.ConvertMemberName(MemberInfo member) { diff --git a/sdk/core/Azure.Core/tests/BinaryDataSerializationTests.cs b/sdk/core/Azure.Core/tests/BinaryDataSerializationTests.cs index f60990b395bf..f9cfd913ac87 100644 --- a/sdk/core/Azure.Core/tests/BinaryDataSerializationTests.cs +++ b/sdk/core/Azure.Core/tests/BinaryDataSerializationTests.cs @@ -2,7 +2,9 @@ // Licensed under the MIT License. using System; +using System.IO; using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; using Azure.Core.Serialization; using NUnit.Framework; @@ -76,6 +78,74 @@ async Task AssertData(BinaryData data) } } + [Test] + public async Task CustomSerializerCanCreateBinaryDataFromCustomType() + { + var payload = new Model { A = "value", B = 5, C = 3 }; + // testing the base ObjectSerializer implementation + var serializer = new CustomSerializer(); + + await AssertData(await serializer.SerializeAsync(payload)); + await AssertData(serializer.Serialize(payload)); + await AssertData(await serializer.SerializeAsync(payload, typeof(Model))); + await AssertData(serializer.Serialize(payload, typeof(Model))); + await AssertData(await serializer.SerializeAsync(payload, null)); + await AssertData(serializer.Serialize(payload, null)); + + async Task AssertData(BinaryData data) + { + Assert.AreEqual(payload.A, data.ToObject(serializer).A); + Assert.AreEqual(payload.B, data.ToObject(serializer).B); + Assert.AreEqual(0, data.ToObject(serializer).C); + Assert.AreEqual(payload.A, (await data.ToObjectAsync(serializer)).A); + Assert.AreEqual(payload.B, (await data.ToObjectAsync(serializer)).B); + Assert.AreEqual(0, (await data.ToObjectAsync(serializer)).C); + } + } + + [Test] + public async Task CustomSerializerCanCreateBinaryDataFromCustomTypePassingBaseType() + { + var payload = new ExtendedModel() { A = "value", B = 5, C = 3, F = 5 }; + // testing the base ObjectSerializer implementation + var serializer = new CustomSerializer(); + + await AssertData(await serializer.SerializeAsync(payload, typeof(Model))); + await AssertData(serializer.Serialize(payload, typeof(Model))); + + async Task AssertData(BinaryData data) + { + Assert.AreEqual(payload.A, data.ToObject(serializer).A); + Assert.AreEqual(payload.B, data.ToObject(serializer).B); + Assert.AreEqual(0, data.ToObject(serializer).C); + Assert.AreEqual(payload.A, (await data.ToObjectAsync(serializer)).A); + Assert.AreEqual(payload.B, (await data.ToObjectAsync(serializer)).B); + Assert.AreEqual(0, (await data.ToObjectAsync(serializer)).C); + Assert.AreEqual(0, (await data.ToObjectAsync(serializer)).F); + } + } + + [Test] + public async Task CustomSerializerCanCreateBinaryDataFromNullObject() + { + Model model = null; + // testing the base ObjectSerializer implementation + var serializer = new CustomSerializer(); + + await AssertData(await serializer.SerializeAsync(model)); + await AssertData(serializer.Serialize(model)); + await AssertData(await serializer.SerializeAsync(model, typeof(Model))); + await AssertData(serializer.Serialize(model, typeof(Model))); + await AssertData(await serializer.SerializeAsync(model, null)); + await AssertData(serializer.Serialize(model, null)); + + async Task AssertData(BinaryData data) + { + Assert.IsNull(data.ToObject(serializer)); + Assert.IsNull(await data.ToObjectAsync(serializer)); + } + } + public class Model { public string A { get; set; } @@ -104,5 +174,22 @@ internal ExtendedModel(int readOnlyD) public int F { get; set; } } + + public class CustomSerializer : ObjectSerializer + { + private static JsonObjectSerializer s_serializer = new JsonObjectSerializer(); + + public override object Deserialize(Stream stream, Type returnType, CancellationToken cancellationToken) + => s_serializer.Deserialize(stream, returnType, cancellationToken); + + public async override ValueTask DeserializeAsync(Stream stream, Type returnType, CancellationToken cancellationToken) + => await s_serializer.DeserializeAsync(stream, returnType, cancellationToken).ConfigureAwait(false); + + public override void Serialize(Stream stream, object value, Type inputType, CancellationToken cancellationToken) + => s_serializer.Serialize(stream, value, inputType, cancellationToken); + + public async override ValueTask SerializeAsync(Stream stream, object value, Type inputType, CancellationToken cancellationToken) + => await s_serializer.SerializeAsync(stream, value, inputType, cancellationToken).ConfigureAwait(false); + } } }