Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/core/Azure.Core/perf/Serializations/ModelXmlModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System.Xml;
using System.Xml.Linq;
using Azure.Core.Tests.Public.ModelSerializationTests.Models;
using Azure.Core.Tests.ModelSerializationTests.Models;

namespace Azure.Core.Perf.Serializations
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Text.Json;

namespace Azure.Core.Serialization
Expand All @@ -16,6 +17,8 @@ public interface IModelJsonSerializable<out T> : IModelSerializable<T>
/// </summary>
/// <param name="writer">The <see cref="Utf8JsonWriter"/> to serialize into.</param>
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
/// <exception cref="InvalidOperationException">If <see cref="ModelSerializerFormat.Wire"/> format is passed in and the model does not use JSON for its wire format.</exception>
#pragma warning disable AZC0014 // Avoid using banned types in public API
void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options);
#pragma warning restore AZC0014 // Avoid using banned types in public API
Expand All @@ -26,6 +29,8 @@ public interface IModelJsonSerializable<out T> : IModelSerializable<T>
/// <param name="reader">The <see cref="Utf8JsonReader"/> to read.</param>
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <returns>A <typeparamref name="T"/> representation of the JSON value.</returns>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
/// <exception cref="InvalidOperationException">If <see cref="ModelSerializerFormat.Wire"/> format is passed in and the model does not use JSON for its wire format.</exception>
#pragma warning disable AZC0014 // Avoid using banned types in public API
T Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options);
#pragma warning restore AZC0014 // Avoid using banned types in public API
Expand Down
4 changes: 2 additions & 2 deletions sdk/core/Azure.Core/src/Serialization/IModelSerializable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public interface IModelSerializable<out T>
/// </summary>
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <returns>A binary representation of the serialized model.</returns>
/// <exception cref="InvalidOperationException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
BinaryData Serialize(ModelSerializerOptions options);

/// <summary>
Expand All @@ -26,7 +26,7 @@ public interface IModelSerializable<out T>
/// <param name="data">The <see cref="BinaryData"/> to parse.</param>
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <returns>A <typeparamref name="T"/> representation of the data.</returns>
/// <exception cref="InvalidOperationException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
T Deserialize(BinaryData data, ModelSerializerOptions options);
}
}
16 changes: 12 additions & 4 deletions sdk/core/Azure.Core/src/Serialization/ModelSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static class ModelSerializer
/// <param name="model">The model to convert.</param>
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <returns>A <see cref="BinaryData"/> representation of the model in the <see cref="ModelSerializerFormat"/> specified by the <paramref name="options"/></returns>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
public static BinaryData Serialize<T>(T model, ModelSerializerOptions? options = default) where T : IModelSerializable<T>
{
options ??= ModelSerializerOptions.DefaultWireOptions;
Expand All @@ -32,6 +33,7 @@ public static BinaryData Serialize<T>(T model, ModelSerializerOptions? options =
/// <param name="model">The model to convert.</param>
/// <param name="format">The <see cref="ModelSerializerFormat"/> to use.</param>
/// <returns>A <see cref="BinaryData"/> representation of the model in the <see cref="ModelSerializerFormat"/> specified by the <paramref name="format"/></returns>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerFormat"/>.</exception>
public static BinaryData Serialize<T>(T model, ModelSerializerFormat format)
where T : IModelSerializable<T>
=> Serialize<T>(model, ModelSerializerOptions.GetOptions(format));
Expand All @@ -43,6 +45,7 @@ public static BinaryData Serialize<T>(T model, ModelSerializerFormat format)
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <returns>A <see cref="BinaryData"/> representation of the model in the <see cref="ModelSerializerFormat"/> specified by the <paramref name="options"/></returns>
/// <exception cref="InvalidOperationException">Throws if <paramref name="model"/> does not implement <see cref="IModelSerializable{T}"/>.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
public static BinaryData Serialize(object model, ModelSerializerOptions? options = default)
{
options ??= ModelSerializerOptions.DefaultWireOptions;
Expand All @@ -63,6 +66,7 @@ public static BinaryData Serialize(object model, ModelSerializerOptions? options
/// <param name="format">The <see cref="ModelSerializerFormat"/> to use.</param>
/// <returns>A <see cref="BinaryData"/> representation of the model in the <see cref="ModelSerializerFormat"/> specified by the <paramref name="format"/></returns>
/// <exception cref="InvalidOperationException">Throws if <paramref name="model"/> does not implement <see cref="IModelSerializable{T}"/>.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerFormat"/>.</exception>
public static BinaryData Serialize(object model, ModelSerializerFormat format)
=> Serialize(model, ModelSerializerOptions.GetOptions(format));

Expand All @@ -72,7 +76,8 @@ public static BinaryData Serialize(object model, ModelSerializerFormat format)
/// <param name="data">The <see cref="BinaryData"/> to convert.</param>
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <returns>A <typeparamref name="T"/> representation of the <see cref="BinaryData"/>.</returns>
/// <exception cref="InvalidOperationException">Throws if <typeparamref name="T"/> does not have a public or internal default constructor.</exception>
/// <exception cref="InvalidOperationException">Throws if <typeparamref name="T"/> does not have a public or internal parameterless constructor.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(BinaryData data, ModelSerializerOptions? options = default) where T : IModelSerializable<T>
{
options ??= ModelSerializerOptions.DefaultWireOptions;
Expand All @@ -86,7 +91,8 @@ public static BinaryData Serialize(object model, ModelSerializerFormat format)
/// <param name="data">The <see cref="BinaryData"/> to convert.</param>
/// <param name="format">The <see cref="ModelSerializerFormat"/> to use.</param>
/// <returns>A <typeparamref name="T"/> representation of the <see cref="BinaryData"/>.</returns>
/// <exception cref="InvalidOperationException">Throws if <typeparamref name="T"/> does not have a public or internal default constructor.</exception>
/// <exception cref="InvalidOperationException">Throws if <typeparamref name="T"/> does not have a public or internal parameterless constructor.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerFormat"/>.</exception>
public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(BinaryData data, ModelSerializerFormat format)
where T : IModelSerializable<T>
=> Deserialize<T>(data, ModelSerializerOptions.GetOptions(format));
Expand All @@ -99,7 +105,8 @@ public static BinaryData Serialize(object model, ModelSerializerFormat format)
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <returns>A <paramref name="returnType"/> representation of the <see cref="BinaryData"/>.</returns>
/// <exception cref="InvalidOperationException">Throws if <paramref name="returnType"/> does not implement <see cref="IModelSerializable{T}"/>.</exception>
/// <exception cref="InvalidOperationException">Throws if <paramref name="returnType"/> does not have a public or internal default constructor.</exception>
/// <exception cref="InvalidOperationException">Throws if <paramref name="returnType"/> does not have a public or internal parameterless constructor.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerOptions.Format"/>.</exception>
public static object Deserialize(BinaryData data, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType, ModelSerializerOptions? options = default)
{
options ??= ModelSerializerOptions.DefaultWireOptions;
Expand All @@ -115,7 +122,8 @@ public static object Deserialize(BinaryData data, [DynamicallyAccessedMembers(Dy
/// <param name="format">The <see cref="ModelSerializerFormat"/> to use.</param>
/// <returns>A <paramref name="returnType"/> representation of the <see cref="BinaryData"/>.</returns>
/// <exception cref="InvalidOperationException">Throws if <paramref name="returnType"/> does not implement <see cref="IModelSerializable{T}"/>.</exception>
/// <exception cref="InvalidOperationException">Throws if <paramref name="returnType"/> does not have a public or internal default constructor.</exception>
/// <exception cref="InvalidOperationException">Throws if <paramref name="returnType"/> does not have a public or internal parameterless constructor.</exception>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerFormat"/>.</exception>
public static object Deserialize(BinaryData data, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType, ModelSerializerFormat format)
=> Deserialize(data, returnType, ModelSerializerOptions.GetOptions(format));

Expand Down
2 changes: 2 additions & 0 deletions sdk/core/Azure.Core/src/Serialization/ModelWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public sealed partial class ModelWriter : IDisposable
/// </summary>
/// <param name="model">The model to serialize.</param>
/// <param name="options">The <see cref="ModelSerializerOptions"/> to use.</param>
/// <exception cref="NotSupportedException">If the model does not support the requested <see cref="ModelSerializerFormat"/>.</exception>
/// <exception cref="InvalidOperationException">If <see cref="ModelSerializerFormat.Wire"/> format is passed in and the model does not use JSON for its wire format.</exception>
public ModelWriter(IModelJsonSerializable<object> model, ModelSerializerOptions options)
{
_model = model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System;
using Azure.Core.Serialization;
using Azure.Core.Tests.Public.ModelSerializationTests.Models;
using Azure.Core.Tests.ModelSerializationTests.Models;
using NUnit.Framework;

namespace Azure.Core.Tests.ModelSerialization
Expand Down
17 changes: 17 additions & 0 deletions sdk/core/Azure.Core/tests/ModelSerialization/ModelWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Azure.Core.Serialization;
using Azure.Core.Tests.Common;
using Azure.Core.Tests.ModelSerializationTests.Models;
using Azure.Core.Tests.ResourceManager.Resources;
using NUnit.Framework;

Expand All @@ -24,6 +25,22 @@ public class ModelWriterTests
private static readonly string _json = File.ReadAllText(TestData.GetLocation("ResourceProviderData.json"));
private static readonly ResourceProviderData _resourceProviderData = ModelSerializer.Deserialize<ResourceProviderData>(BinaryData.FromString(_json));

[Test]
public void ThrowsIfUnsupportedFormat()
{
ModelXml model = ModelSerializer.Deserialize<ModelXml>(BinaryData.FromString(File.ReadAllText(TestData.GetLocation("ModelXml.xml"))));
ModelWriter writer = new ModelWriter(model, new ModelSerializerOptions("x"));
Assert.Throws<NotSupportedException>(() => writer.ToBinaryData());
}

[Test]
public void ThrowsIfMismatch()
{
ModelXml model = ModelSerializer.Deserialize<ModelXml>(BinaryData.FromString(File.ReadAllText(TestData.GetLocation("ModelXml.xml"))));
ModelWriter writer = new ModelWriter(model, ModelSerializerOptions.DefaultWireOptions);
Assert.Throws<InvalidOperationException>(() => writer.ToBinaryData());
}

[Test]
public async Task HappyPath()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using System.Xml.Serialization;
using Azure.Core.Serialization;

namespace Azure.Core.Tests.Public.ModelSerializationTests.Models
namespace Azure.Core.Tests.ModelSerializationTests.Models
{
[XmlRoot("ChildTag")]
public class ChildModelXml : IXmlSerializable, IModelSerializable<ChildModelXml>, IModelJsonSerializable<ChildModelXml>, IUtf8JsonSerializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Text.Json;
using Azure.Core.Serialization;

namespace Azure.Core.Tests.Public.ModelSerializationTests.Models
namespace Azure.Core.Tests.ModelSerializationTests.Models
{
[UnknownSubclass(typeof(UnknownBaseModel))]
public abstract class BaseModel : IUtf8JsonSerializable, IModelJsonSerializable<BaseModel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Text.Json;
using Azure.Core.Serialization;

namespace Azure.Core.Tests.Public.ModelSerializationTests.Models
namespace Azure.Core.Tests.ModelSerializationTests.Models
{
public class ModelX : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable<ModelX>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Text.Json;
using Azure.Core.Serialization;

namespace Azure.Core.Tests.Public.ModelSerializationTests.Models
namespace Azure.Core.Tests.ModelSerializationTests.Models
{
public class ModelY : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable<ModelY>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Text.Json;
using Azure.Core.Serialization;

namespace Azure.Core.Tests.Public.ModelSerializationTests.Models
namespace Azure.Core.Tests.ModelSerializationTests.Models
{
internal class UnknownBaseModel : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable<BaseModel>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using System.Xml.Serialization;
using Azure.Core.Serialization;

namespace Azure.Core.Tests.Public.ModelSerializationTests.Models
namespace Azure.Core.Tests.ModelSerializationTests.Models
{
[XmlRoot("Tag")]
public class ModelXml : IXmlSerializable, IModelSerializable<ModelXml>, IModelJsonSerializable<ModelXml>, IUtf8JsonSerializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System;
using System.Linq;
using Azure.Core.Serialization;
using Azure.Core.Tests.Public.ModelSerializationTests.Models;
using Azure.Core.Tests.ModelSerializationTests.Models;
using NUnit.Framework;

namespace Azure.Core.Tests.Public.ModelSerializationTests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,26 @@ public void ThrowsIfUnknownFormat()
}
}

[Test]
public void ThrowsIfWireIsNotJson()
{
if (ModelInstance is IModelJsonSerializable<T> jsonModel && IsXmlWireFormat)
{
Assert.Throws<InvalidOperationException>(() => jsonModel.Serialize(new Utf8JsonWriter(new MemoryStream()), new ModelSerializerOptions(ModelSerializerFormat.Wire)));
Utf8JsonReader reader = new Utf8JsonReader(new byte[] { });
bool exceptionCaught = false;
try
{
jsonModel.Deserialize(ref reader, new ModelSerializerOptions(ModelSerializerFormat.Wire));
}
catch (InvalidOperationException)
{
exceptionCaught = true;
}
Assert.IsTrue(exceptionCaught, "Expected InvalidOperationException to be thrown when deserializing wire format as json");
}
}

[Test]
public void CastNull()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Azure.Core.Serialization;
using Azure.Core.Tests.Public.ModelSerializationTests.Models;
using Azure.Core.Tests.ModelSerializationTests.Models;
using NUnit.Framework;

namespace Azure.Core.Tests.Public.ModelSerializationTests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ protected override string GetExpectedResult(ModelSerializerFormat format)
if (format.Equals(ModelSerializerFormat.Json))
expectedSerializedString += ",\"readOnlyProperty\":\"ReadOnly\"";
expectedSerializedString += ",\"childTag\":{\"childValue\":\"ChildRed\"";
//TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions
//if (format.Equals(ModelSerializerFormat.Json))
// expectedSerializedString += ",\"childReadOnlyProperty\":\"ChildReadOnly\"";
if (format.Equals(ModelSerializerFormat.Json))
expectedSerializedString += ",\"childReadOnlyProperty\":\"ChildReadOnly\"";
expectedSerializedString += "}}";
return expectedSerializedString;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using System.Xml;
using Azure.Core.Serialization;
using Azure.Core.Tests.Common;
using Azure.Core.Tests.Public.ModelSerializationTests.Models;
using Azure.Core.Tests.ModelSerializationTests.Models;
using NUnit.Framework;

namespace Azure.Core.Tests.Public.ModelSerializationTests
Expand Down
Loading