diff --git a/sdk/core/Azure.Core/api/Azure.Core.net461.cs b/sdk/core/Azure.Core/api/Azure.Core.net461.cs index 3f774979daad..c4bc82dc2a57 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net461.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net461.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,12 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class DeserializationProxyAttribute : System.Attribute + { + public DeserializationProxyAttribute(System.Type proxyType) { } + public System.Type ProxyType { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1117,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1145,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? ObjectSerializerResolver { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/api/Azure.Core.net472.cs b/sdk/core/Azure.Core/api/Azure.Core.net472.cs index 3f774979daad..c4bc82dc2a57 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net472.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net472.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,12 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class DeserializationProxyAttribute : System.Attribute + { + public DeserializationProxyAttribute(System.Type proxyType) { } + public System.Type ProxyType { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1117,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1145,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? ObjectSerializerResolver { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected 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 a1bbd8de4d83..d053740875a0 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1078,6 +1080,13 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class DeserializationProxyAttribute : System.Attribute + { + public DeserializationProxyAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type proxyType) { } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] + public System.Type ProxyType { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1112,6 +1121,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1130,6 +1149,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object? Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object? Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals([System.Diagnostics.CodeAnalysis.AllowNullAttribute] object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? ObjectSerializerResolver { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs b/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs index dec24e418149..a56c392b410e 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1079,6 +1081,13 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class DeserializationProxyAttribute : System.Attribute + { + public DeserializationProxyAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type proxyType) { } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] + public System.Type ProxyType { get { throw null; } } + } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("This class utilizes reflection-based JSON serialization and deserialization which is not compatible with trimming.")] [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable @@ -1114,6 +1123,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("This class uses reflection-based JSON serialization and deserialization that is not compatible with trimming.")] public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { @@ -1133,6 +1152,55 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The constructors of the type being deserialized are dynamically accessed and may be trimmed.")] + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object? Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object? Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals([System.Diagnostics.CodeAnalysis.AllowNullAttribute] object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? ObjectSerializerResolver { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs b/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs index 3f774979daad..c4bc82dc2a57 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,12 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class DeserializationProxyAttribute : System.Attribute + { + public DeserializationProxyAttribute(System.Type proxyType) { } + public System.Type ProxyType { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1117,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1145,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? ObjectSerializerResolver { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected 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 3f774979daad..c4bc82dc2a57 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,12 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class DeserializationProxyAttribute : System.Attribute + { + public DeserializationProxyAttribute(System.Type proxyType) { } + public System.Type ProxyType { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1117,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1145,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object? Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T? Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? ObjectSerializerResolver { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelContent/LargeModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/LargeModel.cs new file mode 100644 index 000000000000..bec72f6746d2 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/LargeModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Resources; + +namespace Azure.Core.Perf.RequestContents.ModelContent +{ + public class LargeModel : ModelContentBenchmark + { + protected override string JsonFileName => "ResourceProviderData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelContent/ModelContentBenchmark.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/ModelContentBenchmark.cs new file mode 100644 index 000000000000..ac3a6acc3819 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/ModelContentBenchmark.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Serialization; + +namespace Azure.Core.Perf.RequestContents.ModelContent +{ + public abstract class ModelContentBenchmark : RequestContentBenchmark> where T : class, IModelSerializable + { + protected override RequestContent CreateRequestContent() + { + return RequestContent.Create(_model); + } + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelContent/SmallModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/SmallModel.cs new file mode 100644 index 000000000000..c485debc8ff8 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/SmallModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Compute; + +namespace Azure.Core.Perf.RequestContents.ModelContent +{ + public class SmallModel : ModelContentBenchmark + { + protected override string JsonFileName => "AvailabilitySetData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/LargeModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/LargeModel.cs new file mode 100644 index 000000000000..059688835f5a --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/LargeModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Resources; + +namespace Azure.Core.Perf.RequestContents.ModelJsonContent +{ + public class LargeModel : ModelJsonContentBenchmark + { + protected override string JsonFileName => "ResourceProviderData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/ModelJsonContentBenchmark.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/ModelJsonContentBenchmark.cs new file mode 100644 index 000000000000..c44d7fb23a22 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/ModelJsonContentBenchmark.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Serialization; + +namespace Azure.Core.Perf.RequestContents.ModelJsonContent +{ + public abstract class ModelJsonContentBenchmark : RequestContentBenchmark> where T : class, IModelJsonSerializable + { + protected override RequestContent CreateRequestContent() + { + return RequestContent.Create(_model); + } + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/SmallModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/SmallModel.cs new file mode 100644 index 000000000000..50c640a6c102 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/SmallModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Compute; + +namespace Azure.Core.Perf.RequestContents.ModelJsonContent +{ + public class SmallModel : ModelJsonContentBenchmark + { + protected override string JsonFileName => "AvailabilitySetData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/RequestContentBenchmark.cs b/sdk/core/Azure.Core/perf/RequestContents/RequestContentBenchmark.cs new file mode 100644 index 000000000000..38f2b2f43a00 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/RequestContentBenchmark.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using Azure.Core.Serialization; +using BenchmarkDotNet.Attributes; + +namespace Azure.Core.Perf.RequestContents +{ + public abstract class RequestContentBenchmark where T : class + { + protected abstract string JsonFileName { get; } + protected abstract RequestContent CreateRequestContent(); + + protected T _model; + private RequestContent _serializedContent; + private MemoryStream _stream; + + [GlobalSetup] + public void GlobalSetup() + { + string json = File.ReadAllText(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName, "TestData", JsonFileName)); + Type modelType = typeof(T).GetGenericArguments()[0]; + _model = ModelSerializer.Deserialize(BinaryData.FromString(json), modelType) as T; + _serializedContent = CreateRequestContent(); + _serializedContent.TryComputeLength(out long length); + _stream = new MemoryStream((int)length); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + _serializedContent.Dispose(); + _serializedContent = null; + } + + [Benchmark] + public void Construct() + { + using RequestContent content = CreateRequestContent(); + } + + [Benchmark] + public long TryComputeLength() + { + using RequestContent content = CreateRequestContent(); + content.TryComputeLength(out long length); + return length; + } + + [Benchmark] + public void WriteTo() + { + _serializedContent.WriteTo(_stream, default); + _stream.Position = 0; + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/AvailabilitySetDataModel.cs b/sdk/core/Azure.Core/perf/Serializations/AvailabilitySetDataModel.cs new file mode 100644 index 000000000000..5bb785e4dcd7 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/AvailabilitySetDataModel.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; +using Azure.Core.Tests.ResourceManager.Compute; + +namespace Azure.Core.Perf.Serializations +{ + public class AvailabilitySetDataModel : JsonBenchmark + { + protected override AvailabilitySetData Deserialize(JsonElement jsonElement) + { + return AvailabilitySetData.DeserializeAvailabilitySetData(jsonElement, _options); + } + + protected override void Serialize(Utf8JsonWriter writer) + { + _model.Serialize(writer); + } + + protected override RequestContent CastToRequestContent() + { + return _model; + } + + protected override AvailabilitySetData CastFromResponse() + { + return (AvailabilitySetData)_response; + } + + protected override string JsonFileName => "AvailabilitySetData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/BenchmarkConfig.cs b/sdk/core/Azure.Core/perf/Serializations/BenchmarkConfig.cs new file mode 100644 index 000000000000..4468174c3df3 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/BenchmarkConfig.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using BenchmarkDotNet.Columns; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Reports; +using Perfolizer.Horology; + +namespace Azure.Core.Perf.Serializations +{ + internal class BenchmarkConfig : ManualConfig + { + public BenchmarkConfig() + { + SummaryStyle = SummaryStyle.Default + .WithTimeUnit(TimeUnit.Microsecond) + .WithSizeUnit(SizeUnit.KB); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/JsonBenchmark.cs b/sdk/core/Azure.Core/perf/Serializations/JsonBenchmark.cs new file mode 100644 index 000000000000..3bf0044b1ae2 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/JsonBenchmark.cs @@ -0,0 +1,193 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using System.Text; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.TestFramework; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Azure.Core.Perf.Serializations +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public abstract class JsonBenchmark where T : class, IModelJsonSerializable + { + private string _json; + protected T _model; + protected Response _response; + protected ModelSerializerOptions _options; + private BinaryData _data; + private JsonDocument _jsonDocument; + + protected abstract T Deserialize(JsonElement jsonElement); + + protected abstract void Serialize(Utf8JsonWriter writer); + + protected abstract RequestContent CastToRequestContent(); + + protected abstract T CastFromResponse(); + + protected abstract string JsonFileName { get; } + + [GlobalSetup] + public void SetUp() + { + _json = File.ReadAllText(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName, "TestData", JsonFileName)); + _data = BinaryData.FromString(_json); + _model = ModelSerializer.Deserialize(_data); + _response = new MockResponse(200); + _response.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(_json)); + _options = ModelSerializerOptions.DefaultWireOptions; + _jsonDocument = JsonDocument.Parse(_json); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public void Serialize_Internal() + { + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + Serialize(writer); + writer.Flush(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCast() + { + using var x = CastToRequestContent(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public bool Serialize_ImplicitCastWithSerialize() + { + using var x = CastToRequestContent(); + return x.TryComputeLength(out var length); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCastWithUsage() + { + using var x = CastToRequestContent(); + x.TryComputeLength(out var length); + using var stream = new MemoryStream((int)length); + x.WriteTo(stream, default); + } + + [Benchmark] + [BenchmarkCategory("ModelJsonConverter")] + public string Serialize_ModelJsonConverter() + { + JsonSerializerOptions options = new JsonSerializerOptions(); + options.Converters.Add(new ModelJsonConverter(ModelSerializerFormat.Wire)); + return JsonSerializer.Serialize(_model, options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializer() + { + return ModelSerializer.Serialize(_model, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelWriter() + { + using var writer = new ModelWriter(_model, _options); + return writer.ToBinaryData(); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializerNonGeneric() + { + return ModelSerializer.Serialize((object)_model, _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public void Serialize_PublicInterface() + { + using var stream = new MemoryStream(_data.ToMemory().Length); + using var writer = new Utf8JsonWriter(stream); + _model.Serialize(writer, _options); + writer.Flush(); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public T Deserialize_Internal() + { + return Deserialize(_jsonDocument.RootElement); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public T Deserialize_ExplicitCast() + { + T result = CastFromResponse(); + _response.ContentStream.Position = 0; //reset for reuse + return result; + } + + [Benchmark] + [BenchmarkCategory("ModelJsonConverter")] + public T Deserialize_ModelJsonConverter() + { + JsonSerializerOptions options = new JsonSerializerOptions(); + options.Converters.Add(new ModelJsonConverter(ModelSerializerFormat.Wire)); + return JsonSerializer.Deserialize(_json, options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public T Deserialize_ModelSerializerFromBinaryData() + { + return ModelSerializer.Deserialize(_data, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public object Deserialize_ModelSerializerFromBinaryDataNonGeneric() + { + return ModelSerializer.Deserialize(_data, typeof(T), _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public T Deserialize_PublicInterfaceFromBinaryData() + { + return _model.Deserialize(_data, _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public T Deserialize_Utf8JsonReaderFromBinaryData() + { + Utf8JsonReader reader = new Utf8JsonReader(_data); + return _model.Deserialize(ref reader, _options); + } + + [Benchmark] + [BenchmarkCategory("JsonDocument")] + public void JsonDocumentFromReader() + { + Utf8JsonReader reader = new Utf8JsonReader(_data); + using var doc = JsonDocument.ParseValue(ref reader); + } + + [Benchmark] + [BenchmarkCategory("JsonDocument")] + public void JsonDocumentFromBinaryData() + { + using var doc = JsonDocument.Parse(_data); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/ModelXmlModel.cs b/sdk/core/Azure.Core/perf/Serializations/ModelXmlModel.cs new file mode 100644 index 000000000000..c6beb83843b6 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/ModelXmlModel.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Xml; +using System.Xml.Linq; +using Azure.Core.Tests.ModelSerializationTests.Models; + +namespace Azure.Core.Perf.Serializations +{ + public class ModelXmlModel : XmlBenchmark + { + protected override string XmlFileName => "ModelXml.xml"; + + protected override ModelXml CastFromResponse() + { + return (ModelXml)_response; + } + + protected override RequestContent CastToRequestContent() + { + return _model; + } + + protected override ModelXml Deserialize(XElement xmlElement) + { + return ModelXml.DeserializeModelXml(xmlElement, _options); + } + + protected override void Serialize(XmlWriter writer) + { + _model.Serialize(writer, null); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/ResourceProviderDataModel.cs b/sdk/core/Azure.Core/perf/Serializations/ResourceProviderDataModel.cs new file mode 100644 index 000000000000..43ba6583edee --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/ResourceProviderDataModel.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; +using Azure.Core.Tests.ResourceManager.Resources; +using BenchmarkDotNet.Attributes; + +namespace Azure.Core.Perf.Serializations +{ + [Config(typeof(BenchmarkConfig))] + public class ResourceProviderDataModel : JsonBenchmark + { + protected override string JsonFileName => "ResourceProviderData.json"; + + protected override ResourceProviderData CastFromResponse() + { + return (ResourceProviderData)_response; + } + + protected override RequestContent CastToRequestContent() + { + return _model; + } + + protected override ResourceProviderData Deserialize(JsonElement jsonElement) + { + return ResourceProviderData.DeserializeResourceProviderData(jsonElement, _options); + } + + protected override void Serialize(Utf8JsonWriter writer) + { + _model.Serialize(writer); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/XmlBenchmark.cs b/sdk/core/Azure.Core/perf/Serializations/XmlBenchmark.cs new file mode 100644 index 000000000000..5b0803983119 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/XmlBenchmark.cs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using Azure.Core.Serialization; +using Azure.Core.TestFramework; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Azure.Core.Perf.Serializations +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public abstract class XmlBenchmark where T : class, IModelSerializable + { + private string _xml; + protected T _model; + protected Response _response; + protected ModelSerializerOptions _options; + private BinaryData _data; + private XElement _element; + + protected abstract T Deserialize(XElement xmlElement); + + protected abstract void Serialize(XmlWriter writer); + + protected abstract RequestContent CastToRequestContent(); + + protected abstract T CastFromResponse(); + + protected abstract string XmlFileName { get; } + + [GlobalSetup] + public void SetUp() + { + _xml = File.ReadAllText(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName, "TestData", XmlFileName)); + _data = BinaryData.FromString(_xml); + _model = ModelSerializer.Deserialize(_data); + _response = new MockResponse(200); + _response.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(_xml)); + _options = ModelSerializerOptions.DefaultWireOptions; + _element = XElement.Parse(_xml); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public void Serialize_Internal() + { + using var stream = new MemoryStream(); + using var writer = XmlWriter.Create(stream); + Serialize(writer); + writer.Flush(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCast() + { + using var x = CastToRequestContent(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public bool Serialize_ImplicitCastWithSerialize() + { + using var x = CastToRequestContent(); + return x.TryComputeLength(out var length); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCastWithUsage() + { + using var x = CastToRequestContent(); + x.TryComputeLength(out var length); + using var stream = new MemoryStream((int)length); + x.WriteTo(stream, default); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializer() + { + return ModelSerializer.Serialize(_model, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializerNonGeneric() + { + return ModelSerializer.Serialize((object)_model, _options); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public T Deserialize_Internal() + { + return Deserialize(_element); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public T Deserialize_ExplicitCast() + { + T result = CastFromResponse(); + _response.ContentStream.Position = 0; //reset for reuse + return result; + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public T Deserialize_ModelSerializerFromBinaryData() + { + return ModelSerializer.Deserialize(_data, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public object Deserialize_ModelSerializerFromBinaryDataNonGeneric() + { + return ModelSerializer.Deserialize(_data, typeof(T), _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public T Deserialize_PublicInterfaceFromBinaryData() + { + return _model.Deserialize(_data, _options); + } + } +} diff --git a/sdk/core/Azure.Core/src/RequestContent.cs b/sdk/core/Azure.Core/src/RequestContent.cs index 439b2aa0178f..fe526d9f41b3 100644 --- a/sdk/core/Azure.Core/src/RequestContent.cs +++ b/sdk/core/Azure.Core/src/RequestContent.cs @@ -90,6 +90,22 @@ public abstract class RequestContent : IDisposable [RequiresDynamicCode(SerializationRequiresUnreferencedCode)] public static RequestContent Create(object serializable) => Create(serializable, JsonObjectSerializer.Default); + /// + /// Creates an instance of that wraps a serialized version of an object. + /// + /// The to serialize. + /// The to use. + /// An instance of that wraps a serialized version of the object. + public static RequestContent Create(IModelSerializable model, ModelSerializerOptions? options = default) => new ModelSerializableContent(model, options ?? ModelSerializerOptions.DefaultWireOptions); + + /// + /// Creates an instance of that wraps a serialized version of an object. + /// + /// The to serialize. + /// The to use. + /// An instance of that wraps a serialized version of the object. + public static RequestContent Create(IModelJsonSerializable model, ModelSerializerOptions? options = default) => new ModelJsonSerializableContent(model, options ?? ModelSerializerOptions.DefaultWireOptions); + /// /// Creates an instance of that wraps a serialized version of an object. /// @@ -228,6 +244,63 @@ public override void Dispose() } } + private sealed class ModelJsonSerializableContent : RequestContent + { + private readonly IModelJsonSerializable _model; + private readonly ModelSerializerOptions _options; + + public ModelJsonSerializableContent(IModelJsonSerializable model, ModelSerializerOptions options) + { + _model = model; + _options = options; + } + + private ModelWriter? _writer; + private ModelWriter Writer => _writer ??= new ModelWriter(_model, _options); + + public override void Dispose() => _writer?.Dispose(); + + public override void WriteTo(Stream stream, CancellationToken cancellation) => Writer.CopyTo(stream, cancellation); + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) => await Writer.CopyToAsync(stream, cancellation).ConfigureAwait(false); + + public override bool TryComputeLength(out long length) => Writer.TryComputeLength(out length); + } + + private sealed class ModelSerializableContent : RequestContent + { + private readonly IModelSerializable _model; + private readonly ModelSerializerOptions _options; + + public ModelSerializableContent(IModelSerializable model, ModelSerializerOptions options) + { + _model = model; + _options = options; + } + + public override void Dispose() { } + + private BinaryData? _data; + private BinaryData Data => _data ??= _model.Serialize(_options); + +#if NETFRAMEWORK || NETSTANDARD2_0 + private byte[]? _bytes; + private byte[] Bytes => _bytes ??= Data.ToArray(); + + public override void WriteTo(Stream stream, CancellationToken cancellation) => stream.Write(Bytes, 0, Bytes.Length); +#else + public override void WriteTo(Stream stream, CancellationToken cancellation) => stream.Write(Data.ToMemory().Span); +#endif + + public override bool TryComputeLength(out long length) + { + length = Data.ToMemory().Length; + return true; + } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) => await stream.WriteAsync(Data.ToMemory(), cancellation).ConfigureAwait(false); + } + private sealed class ArrayContent : RequestContent { private readonly byte[] _bytes; diff --git a/sdk/core/Azure.Core/src/Serialization/DeserializationProxyAttribute.cs b/sdk/core/Azure.Core/src/Serialization/DeserializationProxyAttribute.cs new file mode 100644 index 000000000000..db9d3d75d879 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/DeserializationProxyAttribute.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Azure.Core.Serialization +{ + /// + /// Attribute class that indicates a proxy to use for deserialization. + /// The proxy must implement and have a public or non-public parameterless constructor. + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class DeserializationProxyAttribute : Attribute + { + /// + /// Instantiates a new instance of the class. + /// + /// + /// The to create and call deserialize on. + /// The must have a public or non-public parameterless constructor. + /// The must implement where T is the type of the abstract class. + /// + public DeserializationProxyAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type proxyType) + { + ProxyType = proxyType; + } + + /// + /// Gets the to create and call deserialize on. + /// The must have a public or non-public parameterless constructor. + /// The must implement where T is the type of the abstract class. + /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + public Type ProxyType { get; } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/IModelJsonSerializable.cs b/sdk/core/Azure.Core/src/Serialization/IModelJsonSerializable.cs new file mode 100644 index 000000000000..6659988e6bd3 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/IModelJsonSerializable.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; + +namespace Azure.Core.Serialization +{ + /// + /// Allows an object to control its own JSON serialization and deserialization. + /// + /// The type to deserialize the JSON value into. + public interface IModelJsonSerializable : IModelSerializable + { + /// + /// Serializes the model to the provided . + /// + /// The to serialize into. + /// The to use. + /// If the model does not support the requested . + /// If format is passed in and the model does not use JSON for its wire format. +#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 + + /// + /// Reads one JSON value (including objects or arrays) from the provided reader and converts it to a model. + /// + /// The to read. + /// The to use. + /// A representation of the JSON value. + /// If the model does not support the requested . + /// If format is passed in and the model does not use JSON for its wire format. +#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 + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/IModelSerializable.cs b/sdk/core/Azure.Core/src/Serialization/IModelSerializable.cs new file mode 100644 index 000000000000..91657484a2e0 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/IModelSerializable.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Core.Serialization +{ + /// + /// Allows an object to control its own serialization and deserialization. + /// The format of the serialization is determined by the implementer. + /// + /// The type the serialized value can be deserialized to. + public interface IModelSerializable + { + /// + /// Serializes the model into a . + /// + /// The to use. + /// A binary representation of the serialized model. + /// If the model does not support the requested . + BinaryData Serialize(ModelSerializerOptions options); + + /// + /// Converts the provided into a model. + /// + /// The to parse. + /// The to use. + /// A representation of the data. + /// If the model does not support the requested . + T Deserialize(BinaryData data, ModelSerializerOptions options); + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelJsonConverter.cs b/sdk/core/Azure.Core/src/Serialization/ModelJsonConverter.cs new file mode 100644 index 000000000000..ab4d29f84162 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelJsonConverter.cs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Azure.Core.Serialization +{ + /// + /// A generic converter which allows to be able to serialize and deserialize any models that implement . + /// +#pragma warning disable AZC0014 // Avoid using banned types in public API +#if !NET5_0 // RequiresUnreferencedCode in net5.0 doesn't have AttributeTargets.Class as a target, but it was added in net6.0 + [RequiresUnreferencedCode("The constructors of the type being deserialized are dynamically accessed and may be trimmed.")] +#endif + public class ModelJsonConverter : JsonConverter> +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + /// + /// Gets the used to serialize and deserialize models. + /// + public ModelSerializerOptions ModelSerializerOptions { get; } + + /// + /// Initializes a new instance of with a default format of . + /// + public ModelJsonConverter() + : this(ModelSerializerFormat.Json) { } + + /// + /// Initializes a new instance of . + /// + /// The format to serialize to and deserialize from. + public ModelJsonConverter(ModelSerializerFormat format) + : this(ModelSerializerOptions.GetOptions(format)) { } + + /// + /// Initializes a new instance of . + /// + /// The to use. + public ModelJsonConverter(ModelSerializerOptions options) + { + ModelSerializerOptions = options; + } + + /// + public override bool CanConvert(Type typeToConvert) + { + return !Attribute.IsDefined(typeToConvert, typeof(JsonConverterAttribute)); + } + + /// +#pragma warning disable AZC0014 // Avoid using banned types in public API + public override IModelJsonSerializable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return (IModelJsonSerializable)ModelSerializer.Deserialize(BinaryData.FromString(document.RootElement.GetRawText()), typeToConvert, ModelSerializerOptions)!; + } + + /// +#pragma warning disable AZC0014 // Avoid using banned types in public API + public override void Write(Utf8JsonWriter writer, IModelJsonSerializable value, JsonSerializerOptions options) +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + value.Serialize(writer, ModelSerializerOptions); + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelSerializer.cs b/sdk/core/Azure.Core/src/Serialization/ModelSerializer.cs new file mode 100644 index 000000000000..4ecec3855930 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelSerializer.cs @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Azure.Core.Serialization +{ + /// + /// Provides functionality to serialize and deserialize Azure models. + /// + public static class ModelSerializer + { + /// + /// Converts the value of a model into a . + /// + /// The type of the value to serialize. + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(T model, ModelSerializerOptions? options = default) where T : IModelSerializable + { + Argument.AssertNotNull(model, nameof(model)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + return model.Serialize(options); + } + + /// + /// Converts the value of a model into a . + /// + /// The type of the value to serialize. + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(T model, ModelSerializerFormat format) + where T : IModelSerializable + => Serialize(model, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the value of a model into a . + /// + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// Throws if does not implement . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(object model, ModelSerializerOptions? options = default) + { + Argument.AssertNotNull(model, nameof(model)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + var iModel = model as IModelSerializable; + if (iModel is null) + { + throw new InvalidOperationException($"{model.GetType().Name} does not implement {nameof(IModelSerializable)}"); + } + + return iModel.Serialize(options); + } + + /// + /// Converts the value of a model into a . + /// + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// Throws if does not implement . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(object model, ModelSerializerFormat format) + => Serialize(model, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the into a . + /// + /// The to convert. + /// The to use. + /// A representation of the . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If is null. + public static T? Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(BinaryData data, ModelSerializerOptions? options = default) where T : IModelSerializable + { + Argument.AssertNotNull(data, nameof(data)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + return GetInstance().Deserialize(data, options); + } + + /// + /// Converts the into a . + /// + /// The to convert. + /// The to use. + /// A representation of the . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If is null. + public static T? Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(BinaryData data, ModelSerializerFormat format) + where T : IModelSerializable + => Deserialize(data, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the into a . + /// + /// The to convert. + /// The type of the objec to convert and return. + /// The to use. + /// A representation of the . + /// Throws if does not implement . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If or are null. + public static object? Deserialize(BinaryData data, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType, ModelSerializerOptions? options = default) + { + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(returnType, nameof(returnType)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + return GetInstance(returnType).Deserialize(data, options); + } + + /// + /// Converts the into a . + /// + /// The to convert. + /// The type of the objec to convert and return. + /// The to use. + /// A representation of the . + /// Throws if does not implement . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If or are null. + public static object? Deserialize(BinaryData data, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType, ModelSerializerFormat format) + => Deserialize(data, returnType, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the value of a model into a . + /// + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// If or are null. + public static BinaryData SerializeCore(IModelJsonSerializable model, ModelSerializerOptions options) + { + Argument.AssertNotNull(model, nameof(model)); + Argument.AssertNotNull(options, nameof(options)); + + using ModelWriter writer = new ModelWriter(model, options); + return writer.ToBinaryData(); + } + + private static IModelSerializable GetInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType) + { + var model = GetObjectInstance(returnType) as IModelSerializable; + if (model is null) + { + throw new InvalidOperationException($"{returnType.Name} does not implement {nameof(IModelSerializable)}"); + } + return model; + } + + private static IModelSerializable GetInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>() where T : IModelSerializable + { + var model = GetObjectInstance(typeof(T)) as IModelSerializable; + if (model is null) + { + throw new InvalidOperationException($"{typeof(T).Name} does not implement {nameof(IModelSerializable)}"); + } + return model; + } + + private static object GetObjectInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType) + { + DeserializationProxyAttribute? attribute = Attribute.GetCustomAttribute(returnType, typeof(DeserializationProxyAttribute), false) as DeserializationProxyAttribute; + Type typeToActivate = attribute is null ? returnType : attribute.ProxyType; + + if (returnType.IsAbstract && attribute is null) + { + throw new InvalidOperationException($"{returnType.Name} must be decorated with {nameof(DeserializationProxyAttribute)} to be used with {nameof(ModelSerializer)}"); + } + + var obj = Activator.CreateInstance(typeToActivate, true); + if (obj is null) + { + throw new InvalidOperationException($"Unable to create instance of {typeToActivate.Name}."); + } + return obj; + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelSerializerFormat.cs b/sdk/core/Azure.Core/src/Serialization/ModelSerializerFormat.cs new file mode 100644 index 000000000000..7a4b8a7ce7f8 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelSerializerFormat.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace Azure.Core.Serialization +{ + /// + /// A format used to specify how a model should be serialized and deserialized. + /// + public readonly partial struct ModelSerializerFormat : IEquatable + { + internal const string JsonValue = "J"; + internal const string WireValue = "W"; + + /// + /// Default format which will serialize all properties including read-only and additional properties. + /// The format will always be JSON. + /// + public static readonly ModelSerializerFormat Json = new ModelSerializerFormat(JsonValue); + + /// + /// Format used to serialize this model when sending as a request to an Azure service. + /// It may not serialize read-only properties or additional properties. + /// The content-type will vary between JSON, XML, etc., depending on the service. + /// + /// Most use cases should prefer a more complete format like that includes + /// read-only and additional properties. + /// + public static readonly ModelSerializerFormat Wire = new ModelSerializerFormat(WireValue); + + private readonly string _value; + + /// + /// Instantiate a new . + /// + public ModelSerializerFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + /// + /// Determines if two values are the same. + /// + /// The first to compare. + /// The second to compare. + /// True if and are the same; otherwise, false. + public static bool operator ==(ModelSerializerFormat left, ModelSerializerFormat right) => left.Equals(right); + + /// + /// Determines if two values are different. + /// + /// The first to compare. + /// The second to compare. + /// True if and are different; otherwise, false. + public static bool operator !=(ModelSerializerFormat left, ModelSerializerFormat right) => !left.Equals(right); + + /// + /// Converts a string to a . + /// + /// The string value to convert. + public static implicit operator ModelSerializerFormat(string value) => new ModelSerializerFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals([System.Diagnostics.CodeAnalysis.AllowNull] object obj) => obj is ModelSerializerFormat other && Equals(other); + + /// + public bool Equals(ModelSerializerFormat other) => string.Equals(_value, other._value, StringComparison.Ordinal); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelSerializerOptions.cs b/sdk/core/Azure.Core/src/Serialization/ModelSerializerOptions.cs new file mode 100644 index 000000000000..610f5f34c22d --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelSerializerOptions.cs @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace Azure.Core.Serialization +{ + /// + /// Provides the client options for serializing models. + /// + public class ModelSerializerOptions + { + private static readonly IReadOnlyDictionary _singletonMap = new Dictionary() + { + { ModelSerializerFormat.Json, new ModelSerializerOptions(ModelSerializerFormat.Json, true) }, + { ModelSerializerFormat.Wire, new ModelSerializerOptions(ModelSerializerFormat.Wire, true) } + }; + + /// + /// Default options for serializing models into the format the Azure serivce is expecting. + /// + public static readonly ModelSerializerOptions DefaultWireOptions = _singletonMap[ModelSerializerFormat.Wire]; + + internal static ModelSerializerOptions GetOptions(ModelSerializerFormat format) + => _singletonMap.TryGetValue(format, out ModelSerializerOptions? options) ? options! : new ModelSerializerOptions(format); + + private bool _isFrozen; + private Func? _genericTypeSerializerCreator; + + /// + /// Initializes a new instance of the class. Defaults to format . + /// + public ModelSerializerOptions() : this(ModelSerializerFormat.Json, false) { } + + /// + /// Initializes a new instance of the class. + /// + /// String that determines of serialized model.. + public ModelSerializerOptions(ModelSerializerFormat format) : this(format, false) { } + + private ModelSerializerOptions(ModelSerializerFormat format, bool isFrozen) + { + Format = format; + _isFrozen = isFrozen; + } + + /// + /// Gets the that determines format of serialized model. + /// + public ModelSerializerFormat Format { get; } + + /// + /// Gets or sets a factory method that returns an based on the provided . + /// Should return null if the type is not supported. + /// + public Func? ObjectSerializerResolver + { + get + { + return _genericTypeSerializerCreator; + } + set + { + if (_isFrozen) + { + throw new InvalidOperationException("Cannot modify static options reference."); + } + + _genericTypeSerializerCreator = value; + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelWriter.SequenceBuilder.cs b/sdk/core/Azure.Core/src/Serialization/ModelWriter.SequenceBuilder.cs new file mode 100644 index 000000000000..ec311ccd0d45 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelWriter.SequenceBuilder.cs @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Buffers; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Azure.Core.Serialization +{ + internal sealed partial class ModelWriter : IDisposable + { + private sealed class SequenceBuilder : IBufferWriter, IDisposable + { + private struct Buffer + { + public byte[] Array; + public int Written; + } + + private volatile Buffer[] _buffers; // this is an array so items can be accessed by ref + private volatile int _count; + private readonly int _segmentSize; + + /// + /// Initializes a new instance of . + /// + /// The size of each buffer segment. + public SequenceBuilder(int segmentSize = 16384) + { + // we perf tested a very large and a small model and found that the performance + // for 4k, 8k, 16k, 32k, was neglible for the small model but had a 30% alloc improvment + // from 4k to 16k on the very large model. + _segmentSize = segmentSize; + _buffers = Array.Empty(); + } + + /// + /// Notifies the that bytes bytes were written to the output or . + /// You must request a new buffer after calling to continue writing more data; you cannot write to a previously acquired buffer. + /// + /// The number of bytes written to the or . + /// + public void Advance(int bytesWritten) + { + ref Buffer last = ref _buffers[_count - 1]; + last.Written += bytesWritten; + if (last.Written > last.Array.Length) + { + throw new ArgumentOutOfRangeException(nameof(bytesWritten)); + } + } + + /// + /// Returns a to write to that is at least the requested size, as specified by the parameter. + /// + /// The minimum length of the returned . If less than 256, a buffer of size 256 will be returned. + /// A memory buffer of at least bytes. If is less than 256, a buffer of size 256 will be returned. + public Memory GetMemory(int sizeHint = 0) + { + if (sizeHint < 256) + { + sizeHint = 256; + } + + int sizeToRent = sizeHint > _segmentSize ? sizeHint : _segmentSize; + + if (_buffers.Length == 0) + { + ExpandBuffers(sizeToRent); + } + + ref Buffer last = ref _buffers[_count - 1]; + Memory free = last.Array.AsMemory(last.Written); + if (free.Length >= sizeHint) + { + return free; + } + + // else allocate a new buffer: + ExpandBuffers(sizeToRent); + + return _buffers[_count - 1].Array; + } + + private readonly object _lock = new object(); + private void ExpandBuffers(int sizeToRent) + { + lock (_lock) + { + int bufferCount = _count == 0 ? 1 : _count * 2; + + Buffer[] resized = new Buffer[bufferCount]; + if (_count > 0) + { + _buffers.CopyTo(resized, 0); + } + _buffers = resized; + _buffers[_count].Array = ArrayPool.Shared.Rent(sizeToRent); + _count = bufferCount == 1 ? bufferCount : _count + 1; + } + } + + /// + /// Returns a to write to that is at least the requested size, as specified by the parameter. + /// + /// The minimum length of the returned . If less than 256, a buffer of size 256 will be returned. + /// A buffer of at least bytes. If is less than 256, a buffer of size 256 will be returned. + public Span GetSpan(int sizeHint = 0) + { + Memory memory = GetMemory(sizeHint); + return memory.Span; + } + + /// + /// Disposes the SequenceWriter and returns the underlying buffers to the pool. + /// + public void Dispose() + { + int bufferCountToFree; + Buffer[] buffersToFree; + lock (_lock) + { + bufferCountToFree = _count; + buffersToFree = _buffers; + _count = 0; + _buffers = Array.Empty(); + } + + for (int i = 0; i < bufferCountToFree; i++) + { + ArrayPool.Shared.Return(buffersToFree[i].Array); + } + } + + /// + public bool TryComputeLength(out long length) + { + length = 0; + for (int i = 0; i < _count; i++) + { + length += _buffers[i].Written; + } + return true; + } + + /// + public void CopyTo(Stream stream, CancellationToken cancellation) + { + for (int i = 0; i < _count; i++) + { + Buffer buffer = _buffers[i]; + stream.Write(buffer.Array, 0, buffer.Written); + } + } + + /// + public async Task CopyToAsync(Stream stream, CancellationToken cancellation) + { + for (int i = 0; i < _count; i++) + { + Buffer buffer = _buffers[i]; + await stream.WriteAsync(buffer.Array, 0, buffer.Written).ConfigureAwait(false); + } + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelWriter.cs b/sdk/core/Azure.Core/src/Serialization/ModelWriter.cs new file mode 100644 index 000000000000..0b5cae45eb75 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelWriter.cs @@ -0,0 +1,197 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace Azure.Core.Serialization +{ + /// + /// Provides an efficient way to serialize into a using multiple pooled buffers. + /// + internal sealed partial class ModelWriter : IDisposable + { + private readonly IModelJsonSerializable _model; + private readonly ModelSerializerOptions _options; + + private readonly object _writeLock = new object(); + private readonly object _readLock = new object(); + + private volatile SequenceBuilder? _sequenceBuilder; + private volatile bool _isDisposed; + + private volatile int _readCount; + + private ManualResetEvent? _readersFinished; + private ManualResetEvent ReadersFinished => _readersFinished ??= new ManualResetEvent(true); + + /// + /// Initializes a new instance of . + /// + /// The model to serialize. + /// The to use. + /// If the model does not support the requested . + /// If format is passed in and the model does not use JSON for its wire format. + public ModelWriter(IModelJsonSerializable model, ModelSerializerOptions options) + { + _model = model; + _options = options; + } + + private SequenceBuilder GetSequenceBuilder() + { + if (_sequenceBuilder is null) + { + lock (_writeLock) + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(ModelWriter)); + } + + if (_sequenceBuilder is null) + { + SequenceBuilder sequenceBuilder = new SequenceBuilder(); + using var jsonWriter = new Utf8JsonWriter(sequenceBuilder); + _model.Serialize(jsonWriter, _options); + jsonWriter.Flush(); + _sequenceBuilder = sequenceBuilder; + } + } + } + return _sequenceBuilder; + } + + internal void CopyTo(Stream stream, CancellationToken cancellation) + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + builder.CopyTo(stream, cancellation); + } + finally + { + DecrementRead(); + } + } + + internal bool TryComputeLength(out long length) + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + return builder.TryComputeLength(out length); + } + finally + { + DecrementRead(); + } + } + + internal async Task CopyToAsync(Stream stream, CancellationToken cancellation) + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + await builder.CopyToAsync(stream, cancellation).ConfigureAwait(false); + } + finally + { + DecrementRead(); + } + } + + /// + /// Converts the to a . + /// + /// A representation of the serialized in JSON format. + public BinaryData ToBinaryData() + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + bool gotLength = builder.TryComputeLength(out long length); + if (length > int.MaxValue) + { + throw new InvalidOperationException($"Length of serialized model is too long. Value was {length} max is {int.MaxValue}"); + } + Debug.Assert(gotLength); + using var stream = new MemoryStream((int)length); + builder.CopyTo(stream, default); + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + finally + { + DecrementRead(); + } + } + + /// + public void Dispose() + { + if (!_isDisposed) + { + lock (_writeLock) + { + if (!_isDisposed) + { + _isDisposed = true; + + if (_readersFinished is null || _readersFinished.WaitOne()) + { + //only dispose if no readers ever happened or if all readers are done + _sequenceBuilder?.Dispose(); + } + + _sequenceBuilder = null; + _readersFinished?.Dispose(); + _readersFinished = null; + } + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void IncrementRead() + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(ModelWriter)); + } + + lock (_readLock) + { + Interlocked.Increment(ref _readCount); + ReadersFinished.Reset(); + } + + if (_isDisposed) + { + DecrementRead(); + throw new ObjectDisposedException(nameof(ModelWriter)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void DecrementRead() + { + lock (_readLock) + { + if (Interlocked.Decrement(ref _readCount) == 0) + { + // notify we reached zero readers in case dispose is waiting + ReadersFinished.Set(); + } + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/ModelSerializerHelper.cs b/sdk/core/Azure.Core/src/Shared/ModelSerializerHelper.cs new file mode 100644 index 000000000000..45481db3c91a --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/ModelSerializerHelper.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Runtime.CompilerServices; +using Azure.Core.Serialization; + +namespace Azure.Core +{ + internal static class ModelSerializerHelper + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ValidateFormat(IModelSerializable model, ModelSerializerFormat format) + { + bool implementsJson = model is IModelJsonSerializable; + bool isValid = (format == ModelSerializerFormat.Json && implementsJson) || format == ModelSerializerFormat.Wire; + if (!isValid) + { + throw new FormatException($"The model {model.GetType().Name} does not support '{format}' format."); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ValidateFormat(IModelSerializable model, ModelSerializerFormat format) => ValidateFormat(model, format); + } +} diff --git a/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj b/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj index 0faa6ea6ffe1..bab1f4cad1a3 100644 --- a/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj +++ b/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj @@ -44,6 +44,7 @@ + diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelJsonConverterTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelJsonConverterTests.cs new file mode 100644 index 000000000000..458fef6c32e2 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelJsonConverterTests.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + public class ModelJsonConverterTests + { + private readonly JsonSerializerOptions _options; + + public ModelJsonConverterTests() + { + _options = new JsonSerializerOptions(); + _options.Converters.Add(new ModelJsonConverter()); + } + + [TestCaseSource(typeof(SerializationTestSource), "NullBinaryData")] + public void ValidateNullBinaryData(BinaryData data) + { + Assert.IsNull(JsonSerializer.Deserialize(data, _options)); + Assert.IsNull(JsonSerializer.Deserialize(data, typeof(ModelX), _options)); + } + + [TestCaseSource(typeof(SerializationTestSource), "InvalidOperationBinaryData")] + public void ValidateInvalidOperationBinaryData(BinaryData data) => ValidateJsonExceptionBinaryData(data); + + [TestCaseSource(typeof(SerializationTestSource), "JsonExceptionBinaryData")] + public void ValidateJsonExceptionBinaryData(BinaryData data) + { + Assert.Throws(() => JsonSerializer.Deserialize(data, _options)); + Assert.Throws(() => JsonSerializer.Deserialize(data, typeof(ModelX), _options)); + } + + [TestCaseSource(typeof(SerializationTestSource), "EmptyObjectBinaryData")] + public void ValidateEmptyObjectBinaryData(BinaryData data) + { + ModelX x = JsonSerializer.Deserialize(data, _options); + Assert.IsNotNull(x); + Assert.IsNull(x.Kind); + + object obj = JsonSerializer.Deserialize(data, typeof(ModelX), _options); + Assert.IsNotNull(obj); + Assert.IsNull(((ModelX)obj).Kind); + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializationContentTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializationContentTests.cs new file mode 100644 index 000000000000..458fbdc875b6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializationContentTests.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + public class ModelSerializationContentTests + { + private const string json = "{\"kind\":\"X\",\"name\":\"Name\",\"xProperty\":100}"; + private ModelX _modelX; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + _modelX = ModelSerializer.Deserialize(BinaryData.FromString(json)); + } + + [Test] + public void CanCalculateLength() + { + //use IModelSerializable + var content = RequestContent.Create((IModelSerializable)_modelX); + Assert.AreEqual("ModelSerializableContent", content.GetType().Name); + content.TryComputeLength(out long lengthNonJson); + Assert.Greater(lengthNonJson, 0); + + //use IModelJsonSerializable + var jsonContent = RequestContent.Create((IModelJsonSerializable)_modelX); + Assert.AreEqual("ModelJsonSerializableContent", jsonContent.GetType().Name); + content.TryComputeLength(out long lengthJson); + Assert.Greater(lengthJson, 0); + + Assert.AreEqual(lengthNonJson, lengthJson); + + //use default + jsonContent = RequestContent.Create(_modelX); + Assert.AreEqual("ModelJsonSerializableContent", jsonContent.GetType().Name); + content.TryComputeLength(out lengthJson); + Assert.Greater(lengthJson, 0); + + Assert.AreEqual(lengthNonJson, lengthJson); + } + + [Test] + public void ValidatePrivateClassType() + { + IModelSerializable modelX = _modelX; + + RequestContent content = RequestContent.Create(modelX); + Assert.AreEqual("ModelSerializableContent", content.GetType().Name); + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerOptionsTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerOptionsTests.cs new file mode 100644 index 000000000000..f6b287ba45f0 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerOptionsTests.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Reflection; +using Azure.Core.Serialization; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + internal class ModelSerializerOptionsTests + { + [Test] + public void ValidatePropertyIsFrozen() => ValidateFrozenInstance(ModelSerializerOptions.DefaultWireOptions); + + [Test] + public void AllInstancesInMapShouldBeFrozen() + { + Dictionary optionsDictionary = typeof(ModelSerializerOptions) + .GetField("_singletonMap", BindingFlags.NonPublic | BindingFlags.Static) + .GetValue(null) as Dictionary; + foreach (var frozen in optionsDictionary.Values) + { + ValidateFrozenInstance(frozen); + } + } + + public void ValidateFrozenInstance(ModelSerializerOptions frozen) + { + Assert.Throws(() => frozen.ObjectSerializerResolver = type => null); + } + + [Test] + public void NewInstanceShouldNotBeFrozen() + { + ModelSerializerOptions nonFrozen = new ModelSerializerOptions(); + Assert.DoesNotThrow(() => nonFrozen.ObjectSerializerResolver = type => null); + } + + [Test] + public void MapAndStaticPropertySameObject() + { + Assert.IsTrue(ReferenceEquals(ModelSerializerOptions.DefaultWireOptions, ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire))); + } + + [Test] + public void MapShouldReturnSingletons() + { + Assert.IsTrue(ReferenceEquals(ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire), ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire))); + Assert.IsTrue(ReferenceEquals(ModelSerializerOptions.GetOptions(ModelSerializerFormat.Json), ModelSerializerOptions.GetOptions(ModelSerializerFormat.Json))); + } + + [Test] + public void MapShouldHaveRightValues() + { + var options = ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire); + Assert.AreEqual(ModelSerializerFormat.Wire, options.Format); + Assert.IsNull(options.ObjectSerializerResolver); + + options = ModelSerializerOptions.GetOptions(ModelSerializerFormat.Json); + Assert.AreEqual(ModelSerializerFormat.Json, options.Format); + Assert.IsNull(options.ObjectSerializerResolver); + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerTests.cs new file mode 100644 index 000000000000..fbf234bf4054 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerTests.cs @@ -0,0 +1,186 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + public class ModelSerializerTests + { + [Test] + public void ArgumentExceptions() + { + Assert.Throws(() => ModelSerializer.Deserialize(null)); + Assert.Throws(() => ModelSerializer.Deserialize(null, typeof(BaseWithNoUnknown))); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(new byte[] { }), null)); + Assert.Throws(() => ModelSerializer.Serialize(null)); + Assert.Throws(() => ModelSerializer.Serialize(null)); + + Assert.Throws(() => ModelSerializer.Deserialize(null, ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Deserialize(null, typeof(BaseWithNoUnknown), ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(new byte[] { }), null, ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Serialize(null, ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Serialize(null, ModelSerializerFormat.Wire)); + + Assert.Throws(() => ModelSerializer.SerializeCore(null, new ModelSerializerOptions())); + Assert.Throws(() => ModelSerializer.SerializeCore(new ModelX(), null)); + } + + [TestCaseSource(typeof(SerializationTestSource), "InvalidOperationBinaryData")] + public void ValidateInvalidOperationBinaryData(BinaryData data) + { + Assert.Throws(() => ModelSerializer.Deserialize(data)); + Assert.Throws(() => ModelSerializer.Deserialize(data, typeof(ModelX))); + } + + [TestCaseSource(typeof(SerializationTestSource), "JsonExceptionBinaryData")] + public void ValidateJsonExceptionBinaryData(BinaryData data) + { + bool gotException = false; + try + { + ModelX x = ModelSerializer.Deserialize(data); + } + catch (Exception ex) + { + Assert.IsTrue(ex.GetType().IsSubclassOf(typeof(JsonException)), $"Expected a subclass of {nameof(JsonException)} but got {ex.GetType().Name}"); + gotException = true; + } + + Assert.IsTrue(gotException, "Did not recieve exception"); + + gotException = false; + try + { + object x = ModelSerializer.Deserialize(data, typeof(ModelX)); + } + catch (Exception ex) + { + Assert.IsTrue(ex.GetType().IsSubclassOf(typeof(JsonException)), $"Expected a subclass of {nameof(JsonException)} but got {ex.GetType().Name}"); + gotException = true; + } + + Assert.IsTrue(gotException, "Did not recieve exception"); + } + + [TestCaseSource(typeof(SerializationTestSource), "NullBinaryData")] + public void ValidateNullBinaryData(BinaryData data) + { + Assert.IsNull(ModelSerializer.Deserialize(data)); + Assert.IsNull(ModelSerializer.Deserialize(data, typeof(ModelX))); + } + + [TestCaseSource(typeof(SerializationTestSource), "EmptyObjectBinaryData")] + public void ValidateEmptyObjectBinaryData(BinaryData data) + { + ModelX x = ModelSerializer.Deserialize(data); + Assert.IsNotNull(x); + Assert.IsNull(x.Kind); + + object obj = ModelSerializer.Deserialize(data, typeof(ModelX)); + Assert.IsNotNull(obj); + Assert.IsNull(((ModelX)obj).Kind); + } + + [Test] + public void ValidateErrorIfUnknownDoesntExist() + { + BaseWithNoUnknown baseInstance = new SubType(); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()))); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()), typeof(BaseWithNoUnknown))); + } + + [Test] + public void ValidateErrorIfNoDefaultCtor() + { + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()))); + } + + [Test] + public void ValidateErrorIfNotImplementInterface() + { + var ex = Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()), typeof(DoesntImplementInterface))); + Assert.IsTrue(ex.Message.Contains("does not implement")); + ex = Assert.Throws(() => ModelSerializer.Serialize(new DoesntImplementInterface())); + Assert.IsTrue(ex.Message.Contains("does not implement")); + } + + public class DoesntImplementInterface { } + + private class SubType : BaseWithNoUnknown, IModelJsonSerializable + { + SubType IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + return new SubType(); + } + + SubType IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return new SubType(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + return; + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + return new BinaryData(Array.Empty()); + } + } + + private abstract class BaseWithNoUnknown : IModelJsonSerializable + { + BaseWithNoUnknown IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + return new SubType(); + } + + BaseWithNoUnknown IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return new SubType(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + return; + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + return new BinaryData(Array.Empty()); + } + } + + public class ModelWithNoDefaultCtor : IModelJsonSerializable + { + public ModelWithNoDefaultCtor(int x) { } + + ModelWithNoDefaultCtor IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + return new ModelWithNoDefaultCtor(1); + } + + ModelWithNoDefaultCtor IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return new ModelWithNoDefaultCtor(1); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + return; + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + return new BinaryData(Array.Empty()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelWriterTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelWriterTests.cs new file mode 100644 index 000000000000..d4bbc80f9a07 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelWriterTests.cs @@ -0,0 +1,346 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using System.Text.Json; +using System.Threading; +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; + +namespace Azure.Core.Tests.ModelSerialization +{ + /// + /// Happy path tests are in the public test project in the ModelTests class using the JsonInterfaceStrategy. + /// This class is used for testing the internal properties of ModelWriter. + /// + public class ModelWriterTests + { + private const int _modelSize = 156000; + private static readonly string _json = File.ReadAllText(TestData.GetLocation("ResourceProviderData/ResourceProviderData.json")); + private static readonly ResourceProviderData _resourceProviderData = ModelSerializer.Deserialize(BinaryData.FromString(_json)); + + [Test] + public void ThrowsIfUnsupportedFormat() + { + ModelXml model = ModelSerializer.Deserialize(BinaryData.FromString(File.ReadAllText(TestData.GetLocation("ModelXml.xml")))); + ModelWriter writer = new ModelWriter(model, new ModelSerializerOptions("x")); + Assert.Throws(() => writer.ToBinaryData()); + } + + [Test] + public void ThrowsIfMismatch() + { + ModelXml model = ModelSerializer.Deserialize(BinaryData.FromString(File.ReadAllText(TestData.GetLocation("ModelXml.xml")))); + ModelWriter writer = new ModelWriter(model, ModelSerializerOptions.DefaultWireOptions); + Assert.Throws(() => writer.ToBinaryData()); + } + + [Test] + public async Task HappyPath() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + Assert.IsTrue(writer.TryComputeLength(out var length)); + Assert.AreEqual(_modelSize, length); + + MemoryStream stream1 = new MemoryStream((int)length); + writer.CopyTo(stream1, default); + Assert.AreEqual(_modelSize, stream1.Length); + + MemoryStream stream2 = new MemoryStream((int)length); + await writer.CopyToAsync(stream2, default); + Assert.AreEqual(_modelSize, stream2.Length); + + CollectionAssert.AreEqual(stream1.ToArray(), stream2.ToArray()); + } + + [Test] + public async Task DisposeWhileConvertToBinaryData() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, i => + { + taskStarted = true; + BinaryData data = null; + try + { + data = writer.ToBinaryData(); + Assert.AreEqual(_modelSize, data.ToMemory().Length); + } + catch (ObjectDisposedException) + { + Assert.IsNull(data); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + [Test] + public async Task DisposeWhileCopyAsync() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, async i => + { + taskStarted = true; + using MemoryStream stream = new MemoryStream(); + try + { + await writer.CopyToAsync(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + } + catch (ObjectDisposedException) + { + Assert.AreEqual(0, stream.Length); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + private static async Task DisposeAfterStart(ModelWriter writer, FieldInfo sequenceField, Task result) + { + writer.Dispose(); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + await result; + + sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + } + + [Test] + public async Task DisposeWhileCopy() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, i => + { + taskStarted = true; + using MemoryStream stream = new MemoryStream(); + try + { + writer.CopyTo(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + } + catch (ObjectDisposedException) + { + Assert.AreEqual(0, stream.Length); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + [Test] + public async Task DisposeWhileGettingLength() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + long length = 0; + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, i => + { + taskStarted = true; + try + { + Assert.IsTrue(writer.TryComputeLength(out var length)); + Assert.AreEqual(_modelSize, length); + } + catch (ObjectDisposedException) + { + Assert.AreEqual(0, length); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + private static void Validate(ModelWriter writer, FieldInfo sequenceField, bool exceptionThrown, long length) + { + // sequenceBuilder should be null because the writer was disposed + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + // The dispose should wait for the serialization to finish + // because of thread timing the dispose might happen before the readCount is incremented + // In this case the length of the stream will be 0 otherwise the length will be the size of the model + // Both cases are expected and valid the idea being that the dispose should wait for the serialization to finish if it starts second + // and if it starts first then the original thread should get an ObjectDisposedException + Assert.AreEqual(exceptionThrown ? 0 : _modelSize, length); + } + + [Test] + public void UseAfterDispose() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + writer.Dispose(); + + Assert.Throws(() => writer.TryComputeLength(out var length)); + Assert.Throws(() => writer.CopyTo(new MemoryStream(), default)); + Assert.ThrowsAsync(async () => await writer.CopyToAsync(new MemoryStream(), default)); + Assert.Throws(() => writer.ToBinaryData()); + Assert.DoesNotThrow(() => writer.Dispose()); + } + + [Test] + public void DisposeWithLoad() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + writer.TryComputeLength(out var length); + Assert.AreEqual(_modelSize, length); + + object sequenceBuilder = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(writer); + Assert.IsNotNull(sequenceBuilder); + + writer.Dispose(); + + // sequenceBuilder should be null because the writer was disposed + sequenceBuilder = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(writer); + Assert.IsNull(sequenceBuilder); + } + + [Test] + public void DisposeWithoutLoad() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + writer.Dispose(); + + // sequenceBuilder should be null because the writer was disposed + object sequenceBuilder = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(writer); + Assert.IsNull(sequenceBuilder); + } + + [TestCase("J")] + [TestCase("W")] + public void ExceptionsAreBubbledUp(string format) + { + ExplodingModel model = new ExplodingModel(); + ModelSerializerOptions options = new ModelSerializerOptions(format); + MemoryStream stream = new MemoryStream(); + + using ModelWriter writer = new ModelWriter(model, options); + Assert.Throws(() => writer.TryComputeLength(out var length)); + Assert.Throws(() => writer.CopyTo(stream, default)); + Assert.ThrowsAsync(async () => await writer.CopyToAsync(stream, default)); + Assert.Throws(() => writer.ToBinaryData()); + } + + [Test] + public void ParallelComputLength() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + Parallel.For(0, 1000000, i => + { + Assert.IsTrue(writer.TryComputeLength(out var length)); + Assert.AreEqual(_modelSize, length); + }); + } + + [Test] + public void ParallelCopy() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + Parallel.For(0, 10000, i => + { + using MemoryStream stream = new MemoryStream(_modelSize); + writer.CopyTo(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + }); + } + + [Test] + public void ParallelCopyAsync() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + Parallel.For(0, 10000, async i => + { + using MemoryStream stream = new MemoryStream(_modelSize); + await writer.CopyToAsync(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + }); + } + + private class ExplodingModel : IModelJsonSerializable + { + ExplodingModel IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + + ExplodingModel IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/SerializationTestSource.cs b/sdk/core/Azure.Core/tests/ModelSerialization/SerializationTestSource.cs new file mode 100644 index 000000000000..1206c63c10e7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/SerializationTestSource.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Azure.Core.Tests.ModelSerialization +{ + internal static class SerializationTestSource + { + private static List InvalidOperationBinaryData = new List + { + new BinaryData("\"\""u8.ToArray()), + new BinaryData("[]"u8.ToArray()), + }; + + private static List JsonExceptionBinaryData = new List + { + new BinaryData(new byte[] { }), + }; + + private static List NullBinaryData = new List + { + new BinaryData("null"u8.ToArray()), + }; + + private static List EmptyObjectBinaryData = new List + { + new BinaryData("{}"u8.ToArray()), + }; + } +} diff --git a/sdk/core/Azure.Core/tests/common/Azure.Core.Tests.Common.csproj b/sdk/core/Azure.Core/tests/common/Azure.Core.Tests.Common.csproj index 3157f0c06a88..a9a98df3a26e 100644 --- a/sdk/core/Azure.Core/tests/common/Azure.Core.Tests.Common.csproj +++ b/sdk/core/Azure.Core/tests/common/Azure.Core.Tests.Common.csproj @@ -13,6 +13,40 @@ + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ChildModelXml.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ChildModelXml.cs new file mode 100644 index 000000000000..fd65e8e10cd1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ChildModelXml.cs @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + [XmlRoot("ChildTag")] + public class ChildModelXml : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + internal ChildModelXml() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// is null. + public ChildModelXml(string value, string readonlyProperty) + { + Argument.AssertNotNull(value, nameof(value)); + + ChildValue = value; + ChildReadOnlyProperty = readonlyProperty; + } + + /// Gets or sets the value. + [XmlElement("ChildValue")] + public string ChildValue { get; set; } + /// Gets or sets the value. + [XmlElement("ChildReadOnlyProperty")] + public string ChildReadOnlyProperty { get; } + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "ChildTag"); + writer.WriteStartElement("ChildValue"); + writer.WriteValue(ChildValue); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ChildReadOnlyProperty"); + writer.WriteValue(ChildReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + internal static ChildModelXml DeserializeChildModelXml(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string value = default; + string readonlyProperty = default; + if (element.Element("ChildValue") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ChildReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + return new ChildModelXml(value, readonlyProperty); + } + + internal static ChildModelXml DeserializeChildModelXml(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string childValue = default; + string childReadOnlyProperty = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("childValue"u8)) + { + childValue = property.Value.GetString(); + continue; + } + if (property.NameEquals("childReadOnlyProperty"u8)) + { + childReadOnlyProperty = property.Value.GetString(); + continue; + } + } + return new ChildModelXml(childValue, childReadOnlyProperty); + } + + ChildModelXml IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeChildModelXml(doc.RootElement, options); + } + else + { + return DeserializeChildModelXml(XElement.Load(data.ToStream()), options); + } + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("childValue"u8); + writer.WriteStringValue(ChildValue); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("childReadOnlyProperty"u8); + writer.WriteStringValue(ChildReadOnlyProperty); + } + writer.WriteEndObject(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + ChildModelXml IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeChildModelXml(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/BaseModel.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/BaseModel.cs new file mode 100644 index 000000000000..ed5e7860c2bd --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/BaseModel.cs @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + [DeserializationProxy(typeof(UnknownBaseModel))] + public abstract class BaseModel : IUtf8JsonSerializable, IModelJsonSerializable + { + private Dictionary _rawData; + + public static implicit operator RequestContent(BaseModel baseModel) + { + if (baseModel == null) + { + return null; + } + + return RequestContent.Create(baseModel, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator BaseModel(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeBaseModel(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + protected internal BaseModel(Dictionary rawData) + { + _rawData = rawData ?? new Dictionary(); + } + + public string Kind { get; internal set; } + public string Name { get; set; } + + protected internal void SerializeRawData(Utf8JsonWriter writer) + { + //write out the raw data + foreach (var property in _rawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static BaseModel DeserializeBaseModel(BinaryData data, ModelSerializerOptions options) + => DeserializeBaseModel(JsonDocument.Parse(data.ToString()).RootElement, options); + + internal static BaseModel DeserializeBaseModel(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + if (element.TryGetProperty("kind", out JsonElement discriminator)) + { + switch (discriminator.GetString()) + { + case "X": + return ModelX.DeserializeModelX(element, options); + case "Y": + return ModelY.DeserializeModelY(element, options); + } + } + + //Deserialize unknown subtype + string kind = default; + Optional name = default; + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("kind"u8)) + { + kind = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new UnknownBaseModel(kind, name, rawData); + } + + BaseModel IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeBaseModel(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + BaseModel IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeBaseModel(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelX.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelX.cs new file mode 100644 index 000000000000..8d854c6818b6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelX.cs @@ -0,0 +1,211 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + public class ModelX : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable + { + public ModelX() + : base(null) + { + Kind = "X"; + } + + internal ModelX(string kind, string name, int xProperty, int? nullProperty, IList fields, IDictionary keyValuePairs, Dictionary rawData) + : base(rawData) + { + Kind = kind; + Name = name; + XProperty = xProperty; + NullProperty = nullProperty; + Fields = fields; + KeyValuePairs = keyValuePairs; + } + + public int XProperty { get; } + public IList Fields { get; } + public int? NullProperty = null; + public IDictionary KeyValuePairs { get; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + public static implicit operator RequestContent(ModelX modelX) + { + if (modelX == null) + { + return null; + } + + return RequestContent.Create(modelX, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelX(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeModelX(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (Optional.IsCollectionDefined(Fields)) + { + writer.WritePropertyName("fields"u8); + writer.WriteStartArray(); + foreach (string field in Fields) + { + writer.WriteStringValue(field); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(NullProperty)) + { + writer.WritePropertyName("nullProperty"u8); + writer.WriteNumberValue(NullProperty.Value); + } + if (Optional.IsCollectionDefined(KeyValuePairs)) + { + writer.WritePropertyName("keyValuePairs"u8); + writer.WriteStartObject(); + foreach (var item in KeyValuePairs) + { + writer.WritePropertyName(item.Key); + if (item.Value == null) + { + writer.WriteNullValue(); + continue; + } + writer.WriteObjectValue(item.Value); + } + writer.WriteEndObject(); + } + + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("xProperty"u8); + writer.WriteNumberValue(XProperty); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static ModelX DeserializeModelX(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string kind = default; + Optional name = default; + int xProperty = default; + Optional nullProperty = default; + Optional> fields = default; + Optional> keyValuePairs = default; + Dictionary rawData = new Dictionary(); + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("kind"u8)) + { + kind = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("fields"u8)) + { + fields = property.Value.EnumerateArray().Select(element => element.GetString()).ToList(); + continue; + } + if (property.NameEquals("nullProperty"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + nullProperty = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("keyValuePairs"u8)) + { + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + keyValuePairs = dictionary; + continue; + } + if (property.NameEquals("xProperty"u8)) + { + xProperty = property.Value.GetInt32(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new ModelX(kind, name, xProperty, Optional.ToNullable(nullProperty), Optional.ToList(fields), Optional.ToDictionary(keyValuePairs), rawData); + } + + ModelX IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeModelX(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + //public method to serialize with internal interface + public void Serialize(Utf8JsonWriter writer) + { + ((IUtf8JsonSerializable)this).Write(writer); + } + + ModelX IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelX(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelY.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelY.cs new file mode 100644 index 000000000000..6dcfb722b852 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelY.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + public class ModelY : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable + { + public ModelY() + : base(null) + { + Kind = "Y"; + } + + internal ModelY(string kind, string name, string yProperty, Dictionary rawData) + : base(rawData) + { + Kind = kind; + Name = name; + YProperty = yProperty; + } + + public string YProperty { get; private set; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("yProperty"u8); + writer.WriteStringValue(YProperty); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static ModelY DeserializeModelY(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string kind = default; + Optional name = default; + Optional yProperty = default; + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("kind"u8)) + { + kind = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("yProperty"u8)) + { + yProperty = property.Value.GetString(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new ModelY(kind, name, yProperty, rawData); + } + + ModelY IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeModelY(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + ModelY IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelY(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/UnknownBaseModel.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/UnknownBaseModel.cs new file mode 100644 index 000000000000..0d9ac6ce152e --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/UnknownBaseModel.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + internal class UnknownBaseModel : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable + { + public UnknownBaseModel() + : base(null) + { + Kind = "Unknown"; + } + + internal UnknownBaseModel(string kind, string name, Dictionary rawData) + : base(rawData) + { + Kind = kind; + Name = name; + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static BaseModel DeserializeUnknownBaseModel(JsonElement element, ModelSerializerOptions options = default) => DeserializeBaseModel(element, options); + + BaseModel IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeUnknownBaseModel(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + BaseModel IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeUnknownBaseModel(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelAsStruct.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelAsStruct.cs new file mode 100644 index 000000000000..6eeb5b8bddf3 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelAsStruct.cs @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + /// The InputAdditionalPropertiesModelStruct. + public readonly partial struct ModelAsStruct : IUtf8JsonSerializable, IModelJsonSerializable, IModelJsonSerializable + { + private readonly Dictionary _rawData; + + /// Initializes a new instance of InputAdditionalPropertiesModelStruct. + /// + /// Additional Properties. + /// + /// is null. + public ModelAsStruct(int id, Dictionary rawData) + { + Id = id; + _rawData = rawData; + } + + /// Gets the id. + public int Id { get; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteNumberValue(Id); + if (_rawData is not null && options.Format == ModelSerializerFormat.Json) + { + foreach (var property in _rawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + public static implicit operator RequestContent(ModelAsStruct model) + { + return RequestContent.Create(model, ModelSerializerOptions.DefaultWireOptions); + } + + ModelAsStruct IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + + internal static ModelAsStruct DeserializeInputAdditionalPropertiesModelStruct(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + int id = default; + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetInt32(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + continue; + } + } + return new ModelAsStruct(id, rawData); + } + + ModelAsStruct IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + + public static explicit operator ModelAsStruct(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument doc = JsonDocument.Parse(response.ContentStream); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + object IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + object IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXDeserializationProxy.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXDeserializationProxy.cs new file mode 100644 index 000000000000..9c0c24e0c8a8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXDeserializationProxy.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + [DeserializationProxy(typeof(ModelX))] + public class ModelXDeserializationProxy + { + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXml.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXml.cs new file mode 100644 index 000000000000..cd5e08b1496d --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXml.cs @@ -0,0 +1,229 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + public class ModelXml : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + internal ModelXml() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public ModelXml(string key, string value, string readonlyProperty, ChildModelXml childModel) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readonlyProperty; + RenamedChildModelXml = childModel; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + [XmlElement("RenamedChildModelXml")] + public ChildModelXml RenamedChildModelXml { get; set; } + + public static implicit operator RequestContent(ModelXml modelXml) + { + if (modelXml == null) + { + return null; + } + + return RequestContent.Create((IModelSerializable)modelXml, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelXml(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeModelXml(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + public void Serialize(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteObjectValue(RenamedChildModelXml, "RenamedChildModelXml"); + writer.WriteEndElement(); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + writer.WritePropertyName("renamedChildModelXml"u8); + writer.WriteObjectValue(RenamedChildModelXml); + writer.WriteEndObject(); + } + + public static ModelXml DeserializeModelXml(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readonlyProperty = default; + ChildModelXml childModelXml = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + if (element.Element("RenamedChildModelXml") is XElement renamedChildModelXmlElement) + { + childModelXml = ChildModelXml.DeserializeChildModelXml(renamedChildModelXmlElement, options); + } + return new ModelXml(key, value, readonlyProperty, childModelXml); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + internal static ModelXml DeserializeModelXml(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + ChildModelXml childModelXml = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + if (property.NameEquals("renamedChildModelXml"u8)) + { + childModelXml = ChildModelXml.DeserializeChildModelXml(property.Value, options); + continue; + } + } + return new ModelXml(key, value, readOnlyProperty, childModelXml); + } + + ModelXml IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeModelXml(doc.RootElement, options); + } + else + { + return DeserializeModelXml(XElement.Load(data.ToStream()), options); + } + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + Serialize(writer, options); + } + + ModelXml IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelXml(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.Serialization.cs new file mode 100644 index 000000000000..e67ec83536e8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.Serialization.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ApiProfile : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ApiProfile DeserializeApiProfile(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional profileVersion = default; + Optional apiVersion = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("profileVersion"u8)) + { + profileVersion = property.Value.GetString(); + continue; + } + if (property.NameEquals("apiVersion"u8)) + { + apiVersion = property.Value.GetString(); + continue; + } + } + return new ApiProfile(profileVersion.Value, apiVersion.Value); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(ProfileVersion)) + { + writer.WritePropertyName("profileVersion"u8); + writer.WriteStringValue(ProfileVersion); + } + if (Optional.IsDefined(ApiVersion)) + { + writer.WritePropertyName("apiVersion"u8); + writer.WriteStringValue(ApiVersion); + } + writer.WriteEndObject(); + } + + private struct ApiProfileProperties + { + public Optional ProfileVersion { get; set; } + public Optional ApiVersion { get; set; } + } + + ApiProfile IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeApiProfile(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ApiProfileProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("profileVersion"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.ProfileVersion = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("apiVersion"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.ApiVersion = reader.GetString(); + return; + } + reader.Skip(); + } + + ApiProfile IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeApiProfile(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.cs new file mode 100644 index 000000000000..2b5e44d73549 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The ApiProfile. + public partial class ApiProfile + { + /// Initializes a new instance of ApiProfile. + internal ApiProfile() + { + } + + /// Initializes a new instance of ApiProfile. + /// The profile version. + /// The API version. + internal ApiProfile(string profileVersion, string apiVersion) + { + ProfileVersion = profileVersion; + ApiVersion = apiVersion; + } + + /// The profile version. + public string ProfileVersion { get; } + /// The API version. + public string ApiVersion { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.Serialization.cs new file mode 100644 index 000000000000..2a99336619a0 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.Serialization.cs @@ -0,0 +1,283 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Compute.Models; +using Azure.Core.Tests.ResourceManager.Models; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Compute +{ + public partial class AvailabilitySetData : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id.ToString()); + } + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(ResourceType.ToString()); + } + if (Optional.IsDefined(Sku)) + { + writer.WritePropertyName("sku"u8); + writer.WriteObjectValue(Sku); + } + if (Optional.IsCollectionDefined(Tags)) + { + writer.WritePropertyName("tags"u8); + writer.WriteStartObject(); + foreach (var item in Tags) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + writer.WritePropertyName("location"u8); + writer.WriteStringValue(Location); + writer.WritePropertyName("properties"u8); + writer.WriteStartObject(); + if (Optional.IsDefined(PlatformUpdateDomainCount)) + { + writer.WritePropertyName("platformUpdateDomainCount"u8); + writer.WriteNumberValue(PlatformUpdateDomainCount.Value); + } + if (Optional.IsDefined(PlatformFaultDomainCount)) + { + writer.WritePropertyName("platformFaultDomainCount"u8); + writer.WriteNumberValue(PlatformFaultDomainCount.Value); + } + if (Optional.IsCollectionDefined(VirtualMachines)) + { + writer.WritePropertyName("virtualMachines"u8); + writer.WriteStartArray(); + foreach (var item in VirtualMachines) + { + JsonSerializer.Serialize(writer, item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(ProximityPlacementGroup)) + { + writer.WritePropertyName("proximityPlacementGroup"u8); + JsonSerializer.Serialize(writer, ProximityPlacementGroup); + } + writer.WriteEndObject(); + writer.WriteEndObject(); + } + + public static AvailabilitySetData DeserializeAvailabilitySetData(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional sku = default; + Optional> tags = default; + AzureLocation location = default; + ResourceIdentifier id = default; + string name = default; + ResourceType type = default; + Optional systemData = default; + Optional platformUpdateDomainCount = default; + Optional platformFaultDomainCount = default; + Optional> virtualMachines = default; + Optional proximityPlacementGroup = default; + Optional> statuses = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("sku"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + sku = ComputeSku.DeserializeComputeSku(property.Value, options); + continue; + } + if (property.NameEquals("tags"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + tags = dictionary; + continue; + } + if (property.NameEquals("location"u8)) + { + location = new AzureLocation(property.Value.GetString()); + continue; + } + if (property.NameEquals("id"u8)) + { + id = new ResourceIdentifier(property.Value.GetString()); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + type = new ResourceType(property.Value.GetString()); + continue; + } + if (property.NameEquals("systemData"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + systemData = JsonSerializer.Deserialize(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("properties"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + property.ThrowNonNullablePropertyIsNull(); + continue; + } + foreach (var property0 in property.Value.EnumerateObject()) + { + if (property0.NameEquals("platformUpdateDomainCount"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + platformUpdateDomainCount = property0.Value.GetInt32(); + continue; + } + if (property0.NameEquals("platformFaultDomainCount"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + platformFaultDomainCount = property0.Value.GetInt32(); + continue; + } + if (property0.NameEquals("virtualMachines"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property0.Value.EnumerateArray()) + { + array.Add(JsonSerializer.Deserialize(item.GetRawText())); + } + virtualMachines = array; + continue; + } + if (property0.NameEquals("proximityPlacementGroup"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + proximityPlacementGroup = JsonSerializer.Deserialize(property0.Value.GetRawText()); + continue; + } + if (property0.NameEquals("statuses"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property0.Value.EnumerateArray()) + { + array.Add(InstanceViewStatus.DeserializeInstanceViewStatus(item, options)); + } + statuses = array; + continue; + } + } + continue; + } + } + return new AvailabilitySetData(id, name, type, systemData.Value, Optional.ToDictionary(tags), location, sku.Value, Optional.ToNullable(platformUpdateDomainCount), Optional.ToNullable(platformFaultDomainCount), Optional.ToList(virtualMachines), proximityPlacementGroup, Optional.ToList(statuses)); + } + + AvailabilitySetData IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeAvailabilitySetData(doc.RootElement, options); + } + + // only used for public access to internal serialize + public void Serialize(Utf8JsonWriter writer) => ((IUtf8JsonSerializable)this).Write(writer); + + private struct AvailabilitySetDataProperties + { + public Optional Sku { get; set; } + public Optional> Tags { get; set; } + public AzureLocation Location { get; set; } + public ResourceIdentifier Id { get; set; } + public string Name { get; set; } + public ResourceType ResourceType { get; set; } + public Optional SystemData { get; set; } + public Optional PlatformUpdateDomainCount { get; set; } + public Optional PlatformFaultDomainCount { get; set; } + public Optional> VirtualMachines { get; set; } + public Optional ProximityPlacementGroup { get; set; } + public Optional> Statuses { get; set; } + } + + AvailabilitySetData IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeAvailabilitySetData(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.cs new file mode 100644 index 000000000000..df38269f1da1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.cs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Compute.Models; +using Azure.Core.Tests.ResourceManager.Models; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Compute +{ + /// + /// A class representing the AvailabilitySet data model. + /// Specifies information about the availability set that the virtual machine should be assigned to. Virtual machines specified in the same availability set are allocated to different nodes to maximize availability. For more information about availability sets, see [Availability sets overview](https://docs.microsoft.com/azure/virtual-machines/availability-set-overview). For more information on Azure planned maintenance, see [Maintenance and updates for Virtual Machines in Azure](https://docs.microsoft.com/azure/virtual-machines/maintenance-and-updates). Currently, a VM can only be added to an availability set at creation time. An existing VM cannot be added to an availability set. + /// + public partial class AvailabilitySetData : TrackedResourceData + { + internal AvailabilitySetData() { } + + public static implicit operator RequestContent(AvailabilitySetData availabilitySetData) + { + if (availabilitySetData is null) + { + return null; + } + + return RequestContent.Create(availabilitySetData, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator AvailabilitySetData(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeAvailabilitySetData(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + /// Initializes a new instance of AvailabilitySetData. + /// The location. + public AvailabilitySetData(AzureLocation location) : base(location) + { + VirtualMachines = new ChangeTrackingList(); + Statuses = new ChangeTrackingList(); + } + + /// Initializes a new instance of AvailabilitySetData. + /// The id. + /// The name. + /// The resourceType. + /// The systemData. + /// The tags. + /// The location. + /// Sku of the availability set, only name is required to be set. See AvailabilitySetSkuTypes for possible set of values. Use 'Aligned' for virtual machines with managed disks and 'Classic' for virtual machines with unmanaged disks. Default value is 'Classic'. + /// Update Domain count. + /// Fault Domain count. + /// A list of references to all virtual machines in the availability set. + /// Specifies information about the proximity placement group that the availability set should be assigned to. Minimum api-version: 2018-04-01. + /// The resource status information. + internal AvailabilitySetData(ResourceIdentifier id, string name, ResourceType resourceType, SystemData systemData, IDictionary tags, AzureLocation location, ComputeSku sku, int? platformUpdateDomainCount, int? platformFaultDomainCount, IList virtualMachines, WritableSubResource proximityPlacementGroup, IReadOnlyList statuses) : base(id, name, resourceType, systemData, tags, location) + { + Sku = sku; + PlatformUpdateDomainCount = platformUpdateDomainCount; + PlatformFaultDomainCount = platformFaultDomainCount; + VirtualMachines = virtualMachines; + ProximityPlacementGroup = proximityPlacementGroup; + Statuses = statuses; + } + + /// Sku of the availability set, only name is required to be set. See AvailabilitySetSkuTypes for possible set of values. Use 'Aligned' for virtual machines with managed disks and 'Classic' for virtual machines with unmanaged disks. Default value is 'Classic'. + public ComputeSku Sku { get; set; } + /// Update Domain count. + public int? PlatformUpdateDomainCount { get; set; } + /// Fault Domain count. + public int? PlatformFaultDomainCount { get; set; } + /// A list of references to all virtual machines in the availability set. + public IList VirtualMachines { get; } + /// Specifies information about the proximity placement group that the availability set should be assigned to. Minimum api-version: 2018-04-01. + internal WritableSubResource ProximityPlacementGroup { get; set; } + /// Gets or sets Id. + public ResourceIdentifier ProximityPlacementGroupId + { + get => ProximityPlacementGroup is null ? default : ProximityPlacementGroup.Id; + set + { + if (ProximityPlacementGroup is null) + ProximityPlacementGroup = new WritableSubResource(); + ProximityPlacementGroup.Id = value; + } + } + + /// The resource status information. + public IReadOnlyList Statuses { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.Serialization.cs new file mode 100644 index 000000000000..483232080d92 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.Serialization.cs @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Linq; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + public partial class ComputeSku : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (Optional.IsDefined(Tier)) + { + writer.WritePropertyName("tier"u8); + writer.WriteStringValue(Tier); + } + if (Optional.IsDefined(Capacity)) + { + writer.WritePropertyName("capacity"u8); + writer.WriteNumberValue(Capacity.Value); + } + writer.WriteEndObject(); + } + + internal static ComputeSku DeserializeComputeSku(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional name = default; + Optional tier = default; + Optional capacity = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("tier"u8)) + { + tier = property.Value.GetString(); + continue; + } + if (property.NameEquals("capacity"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + capacity = property.Value.GetInt64(); + continue; + } + } + return new ComputeSku(name.Value, tier.Value, Optional.ToNullable(capacity)); + } + + private struct ComputeSkuProperties + { + public Optional Name { get; set; } + public Optional Tier { get; set; } + public Optional Capacity { get; set; } + } + + ComputeSku IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeComputeSku(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ComputeSkuProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("name"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Name = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("tier"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Tier = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("capacity"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Capacity = reader.GetInt64(); + return; + } + reader.Skip(); + } + + ComputeSku IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeComputeSku(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.cs new file mode 100644 index 000000000000..ae8ec908b7e1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + /// Describes a virtual machine scale set sku. NOTE: If the new VM SKU is not supported on the hardware the scale set is currently on, you need to deallocate the VMs in the scale set before you modify the SKU name. + public partial class ComputeSku + { + /// Initializes a new instance of ComputeSku. + public ComputeSku() + { + } + + /// Initializes a new instance of ComputeSku. + /// The sku name. + /// Specifies the tier of virtual machines in a scale set.<br /><br /> Possible Values:<br /><br /> **Standard**<br /><br /> **Basic**. + /// Specifies the number of virtual machines in the scale set. + internal ComputeSku(string name, string tier, long? capacity) + { + Name = name; + Tier = tier; + Capacity = capacity; + } + + /// The sku name. + public string Name { get; set; } + /// Specifies the tier of virtual machines in a scale set.<br /><br /> Possible Values:<br /><br /> **Standard**<br /><br /> **Basic**. + public string Tier { get; set; } + /// Specifies the number of virtual machines in the scale set. + public long? Capacity { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.Serialization.cs new file mode 100644 index 000000000000..879117da9755 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.Serialization.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + internal static partial class ComputeStatusLevelTypeExtensions + { + public static string ToSerialString(this ComputeStatusLevelType value) => value switch + { + ComputeStatusLevelType.Info => "Info", + ComputeStatusLevelType.Warning => "Warning", + ComputeStatusLevelType.Error => "Error", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ComputeStatusLevelType value.") + }; + + public static ComputeStatusLevelType ToComputeStatusLevelType(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Info")) return ComputeStatusLevelType.Info; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Warning")) return ComputeStatusLevelType.Warning; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Error")) return ComputeStatusLevelType.Error; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ComputeStatusLevelType value."); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.cs new file mode 100644 index 000000000000..196fb7183671 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + /// The level code. + public enum ComputeStatusLevelType + { + /// Info. + Info, + /// Warning. + Warning, + /// Error. + Error + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/CreatedByType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/CreatedByType.cs new file mode 100644 index 000000000000..ce682d85bea6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/CreatedByType.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// The type of identity that created the resource. + public readonly partial struct CreatedByType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreatedByType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UserValue = "User"; + private const string ApplicationValue = "Application"; + private const string ManagedIdentityValue = "ManagedIdentity"; + private const string KeyValue = "Key"; + + /// User. + public static CreatedByType User { get; } = new CreatedByType(UserValue); + /// Application. + public static CreatedByType Application { get; } = new CreatedByType(ApplicationValue); + /// ManagedIdentity. + public static CreatedByType ManagedIdentity { get; } = new CreatedByType(ManagedIdentityValue); + /// Key. + public static CreatedByType Key { get; } = new CreatedByType(KeyValue); + /// Determines if two values are the same. + public static bool operator ==(CreatedByType left, CreatedByType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreatedByType left, CreatedByType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreatedByType(string value) => new CreatedByType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreatedByType other && Equals(other); + /// + public bool Equals(CreatedByType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.Serialization.cs new file mode 100644 index 000000000000..472083e903b8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.Serialization.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Globalization; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + public partial class InstanceViewStatus : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Code)) + { + writer.WritePropertyName("code"u8); + writer.WriteStringValue(Code); + } + if (Optional.IsDefined(Level)) + { + writer.WritePropertyName("level"u8); + writer.WriteStringValue(Level.Value.ToSerialString()); + } + if (Optional.IsDefined(DisplayStatus)) + { + writer.WritePropertyName("displayStatus"u8); + writer.WriteStringValue(DisplayStatus); + } + if (Optional.IsDefined(Message)) + { + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + } + if (Optional.IsDefined(Time)) + { + writer.WritePropertyName("time"u8); + writer.WriteStringValue(Time.Value, "O"); + } + writer.WriteEndObject(); + } + + internal static InstanceViewStatus DeserializeInstanceViewStatus(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional code = default; + Optional level = default; + Optional displayStatus = default; + Optional message = default; + Optional time = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("code"u8)) + { + code = property.Value.GetString(); + continue; + } + if (property.NameEquals("level"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + level = property.Value.GetString().ToComputeStatusLevelType(); + continue; + } + if (property.NameEquals("displayStatus"u8)) + { + displayStatus = property.Value.GetString(); + continue; + } + if (property.NameEquals("message"u8)) + { + message = property.Value.GetString(); + continue; + } + if (property.NameEquals("time"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + time = property.Value.GetDateTimeOffset("O"); + continue; + } + } + return new InstanceViewStatus(code.Value, Optional.ToNullable(level), displayStatus.Value, message.Value, Optional.ToNullable(time)); + } + + private struct InstanceViewStatusProperties + { + public Optional Code { get; set; } + public Optional Level { get; set; } + public Optional DisplayStatus { get; set; } + public Optional Message { get; set; } + public Optional Time { get; set; } + } + + InstanceViewStatus IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeInstanceViewStatus(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref InstanceViewStatusProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("code"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Code = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("level"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Level = reader.GetString().ToComputeStatusLevelType(); + return; + } + if (propertyName.SequenceEqual("displayStatus"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.DisplayStatus = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("message"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Message = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("time"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Time = DateTimeOffset.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + return; + } + reader.Skip(); + } + + InstanceViewStatus IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeInstanceViewStatus(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.cs new file mode 100644 index 000000000000..66891bc6032b --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + /// Instance view status. + public partial class InstanceViewStatus + { + /// Initializes a new instance of InstanceViewStatus. + public InstanceViewStatus() + { + } + + /// Initializes a new instance of InstanceViewStatus. + /// The status code. + /// The level code. + /// The short localizable label for the status. + /// The detailed status message, including for alerts and error messages. + /// The time of the status. + internal InstanceViewStatus(string code, ComputeStatusLevelType? level, string displayStatus, string message, DateTimeOffset? time) + { + Code = code; + Level = level; + DisplayStatus = displayStatus; + Message = message; + Time = time; + } + + /// The status code. + public string Code { get; set; } + /// The level code. + public ComputeStatusLevelType? Level { get; set; } + /// The short localizable label for the status. + public string DisplayStatus { get; set; } + /// The detailed status message, including for alerts and error messages. + public string Message { get; set; } + /// The time of the status. + public DateTimeOffset? Time { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderAuthorizationConsentState.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderAuthorizationConsentState.cs new file mode 100644 index 000000000000..6268124cb3f6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderAuthorizationConsentState.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The provider authorization consent state. + public readonly partial struct ProviderAuthorizationConsentState : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ProviderAuthorizationConsentState(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string NotSpecifiedValue = "NotSpecified"; + private const string RequiredValue = "Required"; + private const string NotRequiredValue = "NotRequired"; + private const string ConsentedValue = "Consented"; + + /// NotSpecified. + public static ProviderAuthorizationConsentState NotSpecified { get; } = new ProviderAuthorizationConsentState(NotSpecifiedValue); + /// Required. + public static ProviderAuthorizationConsentState Required { get; } = new ProviderAuthorizationConsentState(RequiredValue); + /// NotRequired. + public static ProviderAuthorizationConsentState NotRequired { get; } = new ProviderAuthorizationConsentState(NotRequiredValue); + /// Consented. + public static ProviderAuthorizationConsentState Consented { get; } = new ProviderAuthorizationConsentState(ConsentedValue); + /// Determines if two values are the same. + public static bool operator ==(ProviderAuthorizationConsentState left, ProviderAuthorizationConsentState right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ProviderAuthorizationConsentState left, ProviderAuthorizationConsentState right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ProviderAuthorizationConsentState(string value) => new ProviderAuthorizationConsentState(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ProviderAuthorizationConsentState other && Equals(other); + /// + public bool Equals(ProviderAuthorizationConsentState other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.Serialization.cs new file mode 100644 index 000000000000..790a860f1a99 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.Serialization.cs @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ProviderExtendedLocation : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ProviderExtendedLocation DeserializeProviderExtendedLocation(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional location = default; + Optional type = default; + Optional> extendedLocations = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("location"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + location = new AzureLocation(property.Value.GetString()); + continue; + } + if (property.NameEquals("type"u8)) + { + type = property.Value.GetString(); + continue; + } + if (property.NameEquals("extendedLocations"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + extendedLocations = array; + continue; + } + } + return new ProviderExtendedLocation(Optional.ToNullable(location), type.Value, Optional.ToList(extendedLocations)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Location)) + { + writer.WritePropertyName("location"u8); + writer.WriteStringValue(Location.Value.DisplayName); + } + if (Optional.IsDefined(ProviderExtendedLocationType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(ProviderExtendedLocationType); + } + if (Optional.IsCollectionDefined(ExtendedLocations)) + { + writer.WritePropertyName("extendedLocations"u8); + writer.WriteStartArray(); + foreach (var item in ExtendedLocations) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + writer.WriteEndObject(); + } + + private struct ProviderExtendedLocationProperties + { + public Optional Location { get; set; } + public Optional ProviderExtendedLocationType { get; set; } + public Optional> ExtendedLocations { get; set; } + } + + ProviderExtendedLocation IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeProviderExtendedLocation(doc.RootElement, options); + } + + ProviderExtendedLocation IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeProviderExtendedLocation(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.cs new file mode 100644 index 000000000000..bcbb99a520d3 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The provider extended location. + public partial class ProviderExtendedLocation + { + /// Initializes a new instance of ProviderExtendedLocation. + internal ProviderExtendedLocation() + { + ExtendedLocations = new ChangeTrackingList(); + } + + /// Initializes a new instance of ProviderExtendedLocation. + /// The azure location. + /// The extended location type. + /// The extended locations for the azure location. + internal ProviderExtendedLocation(AzureLocation? location, string providerExtendedLocationType, IReadOnlyList extendedLocations) + { + Location = location; + ProviderExtendedLocationType = providerExtendedLocationType; + ExtendedLocations = extendedLocations; + } + + /// The azure location. + public AzureLocation? Location { get; } + /// The extended location type. + public string ProviderExtendedLocationType { get; } + /// The extended locations for the azure location. + public IReadOnlyList ExtendedLocations { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.Serialization.cs new file mode 100644 index 000000000000..cd9cff632635 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.Serialization.cs @@ -0,0 +1,283 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ProviderResourceType : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ProviderResourceType DeserializeProviderResourceType(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional resourceType = default; + Optional> locations = default; + Optional> locationMappings = default; + Optional> aliases = default; + Optional> apiVersions = default; + Optional defaultApiVersion = default; + Optional> zoneMappings = default; + Optional> apiProfiles = default; + Optional capabilities = default; + Optional> properties = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("resourceType"u8)) + { + resourceType = property.Value.GetString(); + continue; + } + if (property.NameEquals("locations"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + locations = array; + continue; + } + if (property.NameEquals("locationMappings"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ProviderExtendedLocation.DeserializeProviderExtendedLocation(item, options)); + } + locationMappings = array; + continue; + } + if (property.NameEquals("aliases"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ResourceTypeAlias.DeserializeResourceTypeAlias(item, options)); + } + aliases = array; + continue; + } + if (property.NameEquals("apiVersions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + apiVersions = array; + continue; + } + if (property.NameEquals("defaultApiVersion"u8)) + { + defaultApiVersion = property.Value.GetString(); + continue; + } + if (property.NameEquals("zoneMappings"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ZoneMapping.DeserializeZoneMapping(item, options)); + } + zoneMappings = array; + continue; + } + if (property.NameEquals("apiProfiles"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ApiProfile.DeserializeApiProfile(item, options)); + } + apiProfiles = array; + continue; + } + if (property.NameEquals("capabilities"u8)) + { + capabilities = property.Value.GetString(); + continue; + } + if (property.NameEquals("properties"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + properties = dictionary; + continue; + } + } + return new ProviderResourceType(resourceType.Value, Optional.ToList(locations), Optional.ToList(locationMappings), Optional.ToList(aliases), Optional.ToList(apiVersions), defaultApiVersion.Value, Optional.ToList(zoneMappings), Optional.ToList(apiProfiles), capabilities.Value, Optional.ToDictionary(properties)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if(Optional.IsDefined(ResourceType)) + { + writer.WritePropertyName("resourceType"u8); + writer.WriteStringValue(ResourceType); + } + if (Optional.IsCollectionDefined(Locations)) + { + writer.WritePropertyName("locations"u8); + writer.WriteStartArray(); + foreach (var item in Locations) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(ApiVersions)) + { + writer.WritePropertyName("apiVersions"u8); + writer.WriteStartArray(); + foreach (var item in ApiVersions) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(DefaultApiVersion)) + { + writer.WritePropertyName("defaultApiVersion"u8); + writer.WriteStringValue(DefaultApiVersion); + } + if (Optional.IsCollectionDefined(ApiProfiles)) + { + writer.WritePropertyName("apiProfiles"u8); + writer.WriteStartArray(); + foreach (var item in ApiProfiles) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(ZoneMappings)) + { + writer.WritePropertyName("zoneMappings"u8); + writer.WriteStartArray(); + foreach (var item in ZoneMappings) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(LocationMappings)) + { + writer.WritePropertyName("locationMappings"u8); + writer.WriteStartArray(); + foreach (var item in LocationMappings) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(Capabilities)) + { + writer.WritePropertyName("capabilities"u8); + writer.WriteStringValue(Capabilities); + } + if (Optional.IsCollectionDefined(Aliases)) + { + writer.WritePropertyName("aliases"u8); + writer.WriteStartArray(); + foreach (var item in Aliases) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(Properties)) + { + writer.WritePropertyName("properties"u8); + writer.WriteStartObject(); + foreach (var item in Properties) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + writer.WriteEndObject(); + } + + private struct ProviderResourceTypeProperties + { + public Optional ResourceType { get; set; } + public Optional> Locations { get; set; } + public Optional> LocationMappings { get; set; } + public Optional> Aliases { get; set; } + public Optional> ApiVersions { get; set; } + public Optional DefaultApiVersion { get; set; } + public Optional> ZoneMappings { get; set; } + public Optional> ApiProfiles { get; set; } + public Optional Capabilities { get; set; } + public Optional> Properties { get; set; } + } + + ProviderResourceType IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeProviderResourceType(doc.RootElement, options); + } + + ProviderResourceType IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeProviderResourceType(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.cs new file mode 100644 index 000000000000..af95577c5916 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.cs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// Resource type managed by the resource provider. + public partial class ProviderResourceType + { + /// Initializes a new instance of ProviderResourceType. + internal ProviderResourceType() + { + Locations = new ChangeTrackingList(); + LocationMappings = new ChangeTrackingList(); + Aliases = new ChangeTrackingList(); + ApiVersions = new ChangeTrackingList(); + ZoneMappings = new ChangeTrackingList(); + ApiProfiles = new ChangeTrackingList(); + Properties = new ChangeTrackingDictionary(); + } + + /// Initializes a new instance of ProviderResourceType. + /// The resource type. + /// The collection of locations where this resource type can be created. + /// The location mappings that are supported by this resource type. + /// The aliases that are supported by this resource type. + /// The API version. + /// The default API version. + /// + /// The API profiles for the resource provider. + /// The additional capabilities offered by this resource type. + /// The properties. + internal ProviderResourceType(string resourceType, IReadOnlyList locations, IReadOnlyList locationMappings, IReadOnlyList aliases, IReadOnlyList apiVersions, string defaultApiVersion, IReadOnlyList zoneMappings, IReadOnlyList apiProfiles, string capabilities, IReadOnlyDictionary properties) + { + ResourceType = resourceType; + Locations = locations; + LocationMappings = locationMappings; + Aliases = aliases; + ApiVersions = apiVersions; + DefaultApiVersion = defaultApiVersion; + ZoneMappings = zoneMappings; + ApiProfiles = apiProfiles; + Capabilities = capabilities; + Properties = properties; + } + + /// The resource type. + public string ResourceType { get; } + /// The collection of locations where this resource type can be created. + public IReadOnlyList Locations { get; } + /// The location mappings that are supported by this resource type. + public IReadOnlyList LocationMappings { get; } + /// The aliases that are supported by this resource type. + public IReadOnlyList Aliases { get; } + /// The API version. + public IReadOnlyList ApiVersions { get; } + /// The default API version. + public string DefaultApiVersion { get; } + /// Gets the zone mappings. + public IReadOnlyList ZoneMappings { get; } + /// The API profiles for the resource provider. + public IReadOnlyList ApiProfiles { get; } + /// The additional capabilities offered by this resource type. + public string Capabilities { get; } + /// The properties. + public IReadOnlyDictionary Properties { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceData.cs new file mode 100644 index 000000000000..488468d0d5d7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceData.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// Common fields that are returned in the response for all Azure Resource Manager resources. + public abstract partial class ResourceData + { + /// Initializes a new instance of Resource. + protected ResourceData() + { + } + + /// Initializes a new instance of Resource. + /// Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. + /// The name of the resource. + /// The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts". + /// Azure Resource Manager metadata containing createdBy and modifiedBy information. + protected ResourceData(ResourceIdentifier id, string name, ResourceType resourceType, SystemData systemData) + { + Id = id; + Name = name; + ResourceType = resourceType; + SystemData = systemData; + } + + /// Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. + public ResourceIdentifier Id { get; } + /// The name of the resource. + public string Name { get; } + /// The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts". + public ResourceType ResourceType { get; } + /// Azure Resource Manager metadata containing createdBy and modifiedBy information. + public SystemData SystemData { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.Serialization.cs new file mode 100644 index 000000000000..4217b5d7054b --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.Serialization.cs @@ -0,0 +1,171 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Resources +{ + public partial class ResourceProviderData : IUtf8JsonSerializable, IModelJsonSerializable + { + public static ResourceProviderData DeserializeResourceProviderData(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional id = default; + Optional @namespace = default; + Optional registrationState = default; + Optional registrationPolicy = default; + Optional> resourceTypes = default; + Optional providerAuthorizationConsentState = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + id = new ResourceIdentifier(property.Value.GetString()); + continue; + } + if (property.NameEquals("namespace"u8)) + { + @namespace = property.Value.GetString(); + continue; + } + if (property.NameEquals("registrationState"u8)) + { + registrationState = property.Value.GetString(); + continue; + } + if (property.NameEquals("registrationPolicy"u8)) + { + registrationPolicy = property.Value.GetString(); + continue; + } + if (property.NameEquals("resourceTypes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ProviderResourceType.DeserializeProviderResourceType(item, options)); + } + resourceTypes = array; + continue; + } + if (property.NameEquals("providerAuthorizationConsentState"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + providerAuthorizationConsentState = new ProviderAuthorizationConsentState(property.Value.GetString()); + continue; + } + } + return new ResourceProviderData(id.Value, @namespace.Value, registrationState.Value, registrationPolicy.Value, Optional.ToList(resourceTypes), Optional.ToNullable(providerAuthorizationConsentState)); + } + + ResourceProviderData IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeResourceProviderData(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + // only used for public access to internal serialize + public void Serialize(Utf8JsonWriter writer) => ((IUtf8JsonSerializable)this).Write(writer); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Id)) + { + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + } + if (Optional.IsDefined(Namespace)) + { + writer.WritePropertyName("namespace"u8); + writer.WriteStringValue(Namespace); + } + if (Optional.IsCollectionDefined(ResourceTypes)) + { + writer.WritePropertyName("resourceTypes"u8); + writer.WriteStartArray(); + foreach (var item in ResourceTypes) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(RegistrationState)) + { + writer.WritePropertyName("registrationState"u8); + writer.WriteStringValue(RegistrationState); + } + if (Optional.IsDefined(RegistrationPolicy)) + { + writer.WritePropertyName("registrationPolicy"u8); + writer.WriteStringValue(RegistrationPolicy); + } + if (Optional.IsDefined(ProviderAuthorizationConsentState)) + { + writer.WritePropertyName("providerAuthorizationConsentState"u8); + writer.WriteStringValue(ProviderAuthorizationConsentState.ToString()); + } + writer.WriteEndObject(); + } + + private struct ResourceProviderDataProperties + { + public Optional Id { get; set; } + public Optional Namespace { get; set; } + public Optional RegistrationState { get; set; } + public Optional RegistrationPolicy { get; set; } + public Optional> ResourceTypes { get; set; } + public Optional ProviderAuthorizationConsentState { get; set; } + } + + ResourceProviderData IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceProviderData(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.cs new file mode 100644 index 000000000000..edb060d13d6c --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Resources +{ + /// + /// A class representing the ResourceProvider data model. + /// Resource provider information. + /// + public partial class ResourceProviderData + { + public static implicit operator RequestContent(ResourceProviderData resourceProviderData) + { + if (resourceProviderData == null) + { + return null; + } + + return RequestContent.Create(resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ResourceProviderData(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeResourceProviderData(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + /// Initializes a new instance of ProviderData. + public ResourceProviderData() + { + ResourceTypes = new ChangeTrackingList(); + } + + /// Initializes a new instance of ProviderData. + /// The provider ID. + /// The namespace of the resource provider. + /// The registration state of the resource provider. + /// The registration policy of the resource provider. + /// The collection of provider resource types. + /// The provider authorization consent state. + internal ResourceProviderData(ResourceIdentifier id, string @namespace, string registrationState, string registrationPolicy, IReadOnlyList resourceTypes, ProviderAuthorizationConsentState? providerAuthorizationConsentState) + { + Id = id; + Namespace = @namespace; + RegistrationState = registrationState; + RegistrationPolicy = registrationPolicy; + ResourceTypes = resourceTypes; + ProviderAuthorizationConsentState = providerAuthorizationConsentState; + } + + /// The provider ID. + public ResourceIdentifier Id { get; } + /// The namespace of the resource provider. + public string Namespace { get; } + /// The registration state of the resource provider. + public string RegistrationState { get; } + /// The registration policy of the resource provider. + public string RegistrationPolicy { get; } + /// The collection of provider resource types. + public IReadOnlyList ResourceTypes { get; } + /// The provider authorization consent state. + public ProviderAuthorizationConsentState? ProviderAuthorizationConsentState { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.Serialization.cs new file mode 100644 index 000000000000..2e7c5044e8a8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.Serialization.cs @@ -0,0 +1,162 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAlias : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAlias DeserializeResourceTypeAlias(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional name = default; + Optional> paths = default; + Optional type = default; + Optional defaultPath = default; + Optional defaultPattern = default; + Optional defaultMetadata = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("paths"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ResourceTypeAliasPath.DeserializeResourceTypeAliasPath(item, options)); + } + paths = array; + continue; + } + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + type = property.Value.GetString().ToResourceTypeAliasType(); + continue; + } + if (property.NameEquals("defaultPath"u8)) + { + defaultPath = property.Value.GetString(); + continue; + } + if (property.NameEquals("defaultPattern"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + defaultPattern = ResourceTypeAliasPattern.DeserializeResourceTypeAliasPattern(property.Value, options); + continue; + } + if (property.NameEquals("defaultMetadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + defaultMetadata = ResourceTypeAliasPathMetadata.DeserializeResourceTypeAliasPathMetadata(property.Value, options); + continue; + } + } + return new ResourceTypeAlias(name.Value, Optional.ToList(paths), Optional.ToNullable(type), defaultPath.Value, defaultPattern.Value, defaultMetadata.Value); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (Optional.IsCollectionDefined(Paths)) + { + writer.WritePropertyName("paths"u8); + writer.WriteStartArray(); + foreach (var item in Paths) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(AliasType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(AliasType.ToString()); + } + if (Optional.IsDefined(DefaultPath)) + { + writer.WritePropertyName("defaultPath"u8); + writer.WriteStringValue(DefaultPath); + } + if (Optional.IsDefined(DefaultPattern)) + { + writer.WritePropertyName("defaultPattern"u8); + writer.WriteObjectValue(DefaultPattern); + } + if (Optional.IsDefined(DefaultMetadata)) + { + writer.WritePropertyName("defaultMetadata"u8); + writer.WriteObjectValue(DefaultMetadata); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasProperties + { + public Optional Name { get; set; } + public Optional> Paths { get; set; } + public Optional AliasType { get; set; } + public Optional DefaultPath { get; set; } + public Optional DefaultPattern { get; set; } + public Optional DefaultMetadata { get; set; } + } + + ResourceTypeAlias IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAlias(doc.RootElement, options); + } + + ResourceTypeAlias IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAlias(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.cs new file mode 100644 index 000000000000..50d7c42be0c7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The alias type. + public partial class ResourceTypeAlias + { + /// Initializes a new instance of ResourceTypeAlias. + internal ResourceTypeAlias() + { + Paths = new ChangeTrackingList(); + } + + /// Initializes a new instance of ResourceTypeAlias. + /// The alias name. + /// The paths for an alias. + /// The type of the alias. + /// The default path for an alias. + /// The default pattern for an alias. + /// The default alias path metadata. Applies to the default path and to any alias path that doesn't have metadata. + internal ResourceTypeAlias(string name, IReadOnlyList paths, ResourceTypeAliasType? aliasType, string defaultPath, ResourceTypeAliasPattern defaultPattern, ResourceTypeAliasPathMetadata defaultMetadata) + { + Name = name; + Paths = paths; + AliasType = aliasType; + DefaultPath = defaultPath; + DefaultPattern = defaultPattern; + DefaultMetadata = defaultMetadata; + } + + /// The alias name. + public string Name { get; } + /// The paths for an alias. + public IReadOnlyList Paths { get; } + /// The type of the alias. + public ResourceTypeAliasType? AliasType { get; } + /// The default path for an alias. + public string DefaultPath { get; } + /// The default pattern for an alias. + public ResourceTypeAliasPattern DefaultPattern { get; } + /// The default alias path metadata. Applies to the default path and to any alias path that doesn't have metadata. + public ResourceTypeAliasPathMetadata DefaultMetadata { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.Serialization.cs new file mode 100644 index 000000000000..536070ad939b --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.Serialization.cs @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAliasPath : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAliasPath DeserializeResourceTypeAliasPath(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional path = default; + Optional> apiVersions = default; + Optional pattern = default; + Optional metadata = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("path"u8)) + { + path = property.Value.GetString(); + continue; + } + if (property.NameEquals("apiVersions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + apiVersions = array; + continue; + } + if (property.NameEquals("pattern"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + pattern = ResourceTypeAliasPattern.DeserializeResourceTypeAliasPattern(property.Value, options); + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + metadata = ResourceTypeAliasPathMetadata.DeserializeResourceTypeAliasPathMetadata(property.Value, options); + continue; + } + } + return new ResourceTypeAliasPath(path.Value, Optional.ToList(apiVersions), pattern.Value, metadata.Value); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Path)) + { + writer.WritePropertyName("path"u8); + writer.WriteStringValue(Path); + } + if (Optional.IsCollectionDefined(ApiVersions)) + { + writer.WritePropertyName("apiVersions"u8); + writer.WriteStartArray(); + foreach (var item in ApiVersions) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(Pattern)) + { + writer.WritePropertyName("pattern"u8); + writer.WriteObjectValue(Pattern); + } + if (Optional.IsDefined(Metadata)) + { + writer.WritePropertyName("metadata"u8); + writer.WriteObjectValue(Metadata); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasPathProperties + { + public Optional Path { get; set; } + public Optional> ApiVersions { get; set; } + public Optional Pattern { get; set; } + public Optional Metadata { get; set; } + } + + ResourceTypeAliasPath IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAliasPath(doc.RootElement, options); + } + + ResourceTypeAliasPath IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAliasPath(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.cs new file mode 100644 index 000000000000..7fb205533f33 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the paths for alias. + public partial class ResourceTypeAliasPath + { + /// Initializes a new instance of ResourceTypeAliasPath. + internal ResourceTypeAliasPath() + { + ApiVersions = new ChangeTrackingList(); + } + + /// Initializes a new instance of ResourceTypeAliasPath. + /// The path of an alias. + /// The API versions. + /// The pattern for an alias path. + /// The metadata of the alias path. If missing, fall back to the default metadata of the alias. + internal ResourceTypeAliasPath(string path, IReadOnlyList apiVersions, ResourceTypeAliasPattern pattern, ResourceTypeAliasPathMetadata metadata) + { + Path = path; + ApiVersions = apiVersions; + Pattern = pattern; + Metadata = metadata; + } + + /// The path of an alias. + public string Path { get; } + /// The API versions. + public IReadOnlyList ApiVersions { get; } + /// The pattern for an alias path. + public ResourceTypeAliasPattern Pattern { get; } + /// The metadata of the alias path. If missing, fall back to the default metadata of the alias. + public ResourceTypeAliasPathMetadata Metadata { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathAttributes.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathAttributes.cs new file mode 100644 index 000000000000..f9a82274f61e --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathAttributes.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The attributes of the token that the alias path is referring to. + public readonly partial struct ResourceTypeAliasPathAttributes : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ResourceTypeAliasPathAttributes(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string NoneValue = "None"; + private const string ModifiableValue = "Modifiable"; + + /// The token that the alias path is referring to has no attributes. + public static ResourceTypeAliasPathAttributes None { get; } = new ResourceTypeAliasPathAttributes(NoneValue); + /// The token that the alias path is referring to is modifiable by policies with 'modify' effect. + public static ResourceTypeAliasPathAttributes Modifiable { get; } = new ResourceTypeAliasPathAttributes(ModifiableValue); + /// Determines if two values are the same. + public static bool operator ==(ResourceTypeAliasPathAttributes left, ResourceTypeAliasPathAttributes right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ResourceTypeAliasPathAttributes left, ResourceTypeAliasPathAttributes right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ResourceTypeAliasPathAttributes(string value) => new ResourceTypeAliasPathAttributes(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ResourceTypeAliasPathAttributes other && Equals(other); + /// + public bool Equals(ResourceTypeAliasPathAttributes other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.Serialization.cs new file mode 100644 index 000000000000..ec4303ae5234 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.Serialization.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAliasPathMetadata : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAliasPathMetadata DeserializeResourceTypeAliasPathMetadata(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional type = default; + Optional attributes = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + type = new ResourceTypeAliasPathTokenType(property.Value.GetString()); + continue; + } + if (property.NameEquals("attributes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + attributes = new ResourceTypeAliasPathAttributes(property.Value.GetString()); + continue; + } + } + return new ResourceTypeAliasPathMetadata(Optional.ToNullable(type), Optional.ToNullable(attributes)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(TokenType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(TokenType.ToString()); + } + if (Optional.IsDefined(Attributes)) + { + writer.WritePropertyName("attributes"u8); + writer.WriteStringValue(Attributes.ToString()); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasPathMetadataProperties + { + public Optional TokenType { get; set; } + public Optional Attributes { get; set; } + } + + ResourceTypeAliasPathMetadata IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAliasPathMetadata(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ResourceTypeAliasPathMetadataProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("type"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.TokenType = new ResourceTypeAliasPathTokenType(reader.GetString()); + return; + } + if (propertyName.SequenceEqual("attributes"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Attributes = new ResourceTypeAliasPathAttributes(reader.GetString()); + return; + } + reader.Skip(); + } + + ResourceTypeAliasPathMetadata IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAliasPathMetadata(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.cs new file mode 100644 index 000000000000..7b965b6ce2b9 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The ResourceTypeAliasPathMetadata. + public partial class ResourceTypeAliasPathMetadata + { + /// Initializes a new instance of ResourceTypeAliasPathMetadata. + internal ResourceTypeAliasPathMetadata() + { + } + + /// Initializes a new instance of ResourceTypeAliasPathMetadata. + /// The type of the token that the alias path is referring to. + /// The attributes of the token that the alias path is referring to. + internal ResourceTypeAliasPathMetadata(ResourceTypeAliasPathTokenType? tokenType, ResourceTypeAliasPathAttributes? attributes) + { + TokenType = tokenType; + Attributes = attributes; + } + + /// The type of the token that the alias path is referring to. + public ResourceTypeAliasPathTokenType? TokenType { get; } + /// The attributes of the token that the alias path is referring to. + public ResourceTypeAliasPathAttributes? Attributes { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathTokenType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathTokenType.cs new file mode 100644 index 000000000000..8b26cdb95a68 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathTokenType.cs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the token that the alias path is referring to. + public readonly partial struct ResourceTypeAliasPathTokenType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ResourceTypeAliasPathTokenType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string NotSpecifiedValue = "NotSpecified"; + private const string AnyValue = "Any"; + private const string StringValue = "String"; + private const string ObjectValue = "Object"; + private const string ArrayValue = "Array"; + private const string IntegerValue = "Integer"; + private const string NumberValue = "Number"; + private const string BooleanValue = "Boolean"; + + /// The token type is not specified. + public static ResourceTypeAliasPathTokenType NotSpecified { get; } = new ResourceTypeAliasPathTokenType(NotSpecifiedValue); + /// The token type can be anything. + public static ResourceTypeAliasPathTokenType Any { get; } = new ResourceTypeAliasPathTokenType(AnyValue); + /// The token type is string. + public static ResourceTypeAliasPathTokenType String { get; } = new ResourceTypeAliasPathTokenType(StringValue); + /// The token type is object. + public static ResourceTypeAliasPathTokenType Object { get; } = new ResourceTypeAliasPathTokenType(ObjectValue); + /// The token type is array. + public static ResourceTypeAliasPathTokenType Array { get; } = new ResourceTypeAliasPathTokenType(ArrayValue); + /// The token type is integer. + public static ResourceTypeAliasPathTokenType Integer { get; } = new ResourceTypeAliasPathTokenType(IntegerValue); + /// The token type is number. + public static ResourceTypeAliasPathTokenType Number { get; } = new ResourceTypeAliasPathTokenType(NumberValue); + /// The token type is boolean. + public static ResourceTypeAliasPathTokenType Boolean { get; } = new ResourceTypeAliasPathTokenType(BooleanValue); + /// Determines if two values are the same. + public static bool operator ==(ResourceTypeAliasPathTokenType left, ResourceTypeAliasPathTokenType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ResourceTypeAliasPathTokenType left, ResourceTypeAliasPathTokenType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ResourceTypeAliasPathTokenType(string value) => new ResourceTypeAliasPathTokenType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ResourceTypeAliasPathTokenType other && Equals(other); + /// + public bool Equals(ResourceTypeAliasPathTokenType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.Serialization.cs new file mode 100644 index 000000000000..0043395ac214 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.Serialization.cs @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAliasPattern : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAliasPattern DeserializeResourceTypeAliasPattern(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional phrase = default; + Optional variable = default; + Optional type = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("phrase"u8)) + { + phrase = property.Value.GetString(); + continue; + } + if (property.NameEquals("variable"u8)) + { + variable = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + type = property.Value.GetString().ToResourceTypeAliasPatternType(); + continue; + } + } + return new ResourceTypeAliasPattern(phrase.Value, variable.Value, Optional.ToNullable(type)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Phrase)) + { + writer.WritePropertyName("phrase"u8); + writer.WriteStringValue(Phrase); + } + if (Optional.IsDefined(Variable)) + { + writer.WritePropertyName("variable"u8); + writer.WriteStringValue(Variable); + } + if (Optional.IsDefined(PatternType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(PatternType.Value.ToSerialString()); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasPatternProperites + { + public Optional Phrase { get; set; } + public Optional Variable { get; set; } + public Optional PatternType { get; set; } + } + + ResourceTypeAliasPattern IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAliasPattern(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ResourceTypeAliasPatternProperites properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("phrase"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Phrase = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("variable"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Variable = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("type"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.PatternType = reader.GetString().ToResourceTypeAliasPatternType(); + return; + } + reader.Skip(); + } + + ResourceTypeAliasPattern IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAliasPattern(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.cs new file mode 100644 index 000000000000..5e0c3d71cf69 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the pattern for an alias path. + public partial class ResourceTypeAliasPattern + { + /// Initializes a new instance of ResourceTypeAliasPattern. + internal ResourceTypeAliasPattern() + { + } + + /// Initializes a new instance of ResourceTypeAliasPattern. + /// The alias pattern phrase. + /// The alias pattern variable. + /// The type of alias pattern. + internal ResourceTypeAliasPattern(string phrase, string variable, ResourceTypeAliasPatternType? patternType) + { + Phrase = phrase; + Variable = variable; + PatternType = patternType; + } + + /// The alias pattern phrase. + public string Phrase { get; } + /// The alias pattern variable. + public string Variable { get; } + /// The type of alias pattern. + public ResourceTypeAliasPatternType? PatternType { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.Serialization.cs new file mode 100644 index 000000000000..b6993ddc0de8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.Serialization.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + internal static partial class ResourceTypeAliasPatternTypeExtensions + { + public static string ToSerialString(this ResourceTypeAliasPatternType value) => value switch + { + ResourceTypeAliasPatternType.NotSpecified => "NotSpecified", + ResourceTypeAliasPatternType.Extract => "Extract", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasPatternType value.") + }; + + public static ResourceTypeAliasPatternType ToResourceTypeAliasPatternType(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "NotSpecified")) return ResourceTypeAliasPatternType.NotSpecified; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Extract")) return ResourceTypeAliasPatternType.Extract; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasPatternType value."); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.cs new file mode 100644 index 000000000000..d54d8e5afe88 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of alias pattern. + public enum ResourceTypeAliasPatternType + { + /// NotSpecified is not allowed. + NotSpecified, + /// Extract is the only allowed value. + Extract + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.Serialization.cs new file mode 100644 index 000000000000..39d50246fe50 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.Serialization.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + internal static partial class ResourceTypeAliasTypeExtensions + { + public static string ToSerialString(this ResourceTypeAliasType value) => value switch + { + ResourceTypeAliasType.NotSpecified => "NotSpecified", + ResourceTypeAliasType.PlainText => "PlainText", + ResourceTypeAliasType.Mask => "Mask", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasType value.") + }; + + public static ResourceTypeAliasType ToResourceTypeAliasType(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "NotSpecified")) return ResourceTypeAliasType.NotSpecified; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "PlainText")) return ResourceTypeAliasType.PlainText; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Mask")) return ResourceTypeAliasType.Mask; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasType value."); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.cs new file mode 100644 index 000000000000..c3fc8585f237 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the alias. + public enum ResourceTypeAliasType + { + /// Alias type is unknown (same as not providing alias type). + NotSpecified, + /// Alias value is not secret. + PlainText, + /// Alias value is secret. + Mask + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.Serialization.cs new file mode 100644 index 000000000000..0acf92d0db1d --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.Serialization.cs @@ -0,0 +1,184 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + [JsonConverter(typeof(SystemDataConverter))] + public partial class SystemData : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteEndObject(); + } + + internal static SystemData DeserializeSystemData(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional createdBy = default; + Optional createdByType = default; + Optional createdAt = default; + Optional lastModifiedBy = default; + Optional lastModifiedByType = default; + Optional lastModifiedAt = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("createdBy"u8)) + { + createdBy = property.Value.GetString(); + continue; + } + if (property.NameEquals("createdByType"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + createdByType = new CreatedByType(property.Value.GetString()); + continue; + } + if (property.NameEquals("createdAt"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + createdAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("lastModifiedBy"u8)) + { + lastModifiedBy = property.Value.GetString(); + continue; + } + if (property.NameEquals("lastModifiedByType"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + lastModifiedByType = new CreatedByType(property.Value.GetString()); + continue; + } + if (property.NameEquals("lastModifiedAt"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + lastModifiedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + } + return new SystemData(createdBy.Value, Optional.ToNullable(createdByType), Optional.ToNullable(createdAt), lastModifiedBy.Value, Optional.ToNullable(lastModifiedByType), Optional.ToNullable(lastModifiedAt)); + } + + private struct SystemDataProperties + { + public Optional CreatedBy { get; set; } + public Optional CreatedByType { get; set; } + public Optional CreatedOn { get; set; } + public Optional LastModifiedBy { get; set; } + public Optional LastModifiedByType { get; set; } + public Optional LastModifiedOn { get; set; } + } + + SystemData IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeSystemData(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref SystemDataProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("createdBy"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.CreatedBy = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("createdByType"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.CreatedByType = new CreatedByType(reader.GetString()); + return; + } + if (propertyName.SequenceEqual("createdAt"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.CreatedOn = DateTimeOffset.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + return; + } + if (propertyName.SequenceEqual("lastModifiedBy"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.LastModifiedBy = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("lastModifiedByType"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.LastModifiedByType = new CreatedByType(reader.GetString()); + return; + } + if (propertyName.SequenceEqual("lastModifiedAt"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.LastModifiedOn = DateTimeOffset.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + return; + } + reader.Skip(); + } + + SystemData IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeSystemData(doc.RootElement, options); + } + + internal partial class SystemDataConverter : JsonConverter + { + public override void Write(Utf8JsonWriter writer, SystemData model, JsonSerializerOptions options) + { + writer.WriteObjectValue(model); + } + public override SystemData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using var document = JsonDocument.ParseValue(ref reader); + return DeserializeSystemData(document.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.cs new file mode 100644 index 000000000000..7df008ba04fe --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// Metadata pertaining to creation and last modification of the resource. + public partial class SystemData + { + /// Initializes a new instance of SystemData. + public SystemData() + { + } + + /// Initializes a new instance of SystemData. + /// The identity that created the resource. + /// The type of identity that created the resource. + /// The timestamp of resource creation (UTC). + /// The identity that last modified the resource. + /// The type of identity that last modified the resource. + /// The timestamp of resource last modification (UTC). + internal SystemData(string createdBy, CreatedByType? createdByType, DateTimeOffset? createdOn, string lastModifiedBy, CreatedByType? lastModifiedByType, DateTimeOffset? lastModifiedOn) + { + CreatedBy = createdBy; + CreatedByType = createdByType; + CreatedOn = createdOn; + LastModifiedBy = lastModifiedBy; + LastModifiedByType = lastModifiedByType; + LastModifiedOn = lastModifiedOn; + } + + /// The identity that created the resource. + public string CreatedBy { get; } + /// The type of identity that created the resource. + public CreatedByType? CreatedByType { get; } + /// The timestamp of resource creation (UTC). + public DateTimeOffset? CreatedOn { get; } + /// The identity that last modified the resource. + public string LastModifiedBy { get; } + /// The type of identity that last modified the resource. + public CreatedByType? LastModifiedByType { get; } + /// The timestamp of resource last modification (UTC). + public DateTimeOffset? LastModifiedOn { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/TrackedResourceData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/TrackedResourceData.cs new file mode 100644 index 000000000000..73899a3ea3f7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/TrackedResourceData.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'. + public abstract partial class TrackedResourceData : ResourceData + { + internal TrackedResourceData() { } + + /// Initializes a new instance of TrackedResource. + /// The geo-location where the resource lives. + protected TrackedResourceData(AzureLocation location) + { + Tags = new ChangeTrackingDictionary(); + Location = location; + } + + /// Initializes a new instance of TrackedResource. + /// Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. + /// The name of the resource. + /// The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts". + /// Azure Resource Manager metadata containing createdBy and modifiedBy information. + /// Resource tags. + /// The geo-location where the resource lives. + protected TrackedResourceData(ResourceIdentifier id, string name, ResourceType resourceType, SystemData systemData, IDictionary tags, AzureLocation location) : base(id, name, resourceType, systemData) + { + Tags = tags; + Location = location; + } + + /// Resource tags. + public IDictionary Tags { get; } + /// The geo-location where the resource lives. + public AzureLocation Location { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.Serialization.cs new file mode 100644 index 000000000000..ac104b6d0050 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.Serialization.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// + /// A class representing a sub-resource that contains only the ID. + /// + [JsonConverter(typeof(WritableSubResourceConverter))] + public partial class WritableSubResource : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + /// + /// Serialize the input WritableSubResource object. + /// + /// Input Json writer. + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + if (writer is null) + { + throw new ArgumentNullException(nameof(writer)); + } + + writer.WriteStartObject(); + if (Optional.IsDefined(Id)) + { + writer.WritePropertyName("id"); + writer.WriteStringValue(Id); + } + writer.WriteEndObject(); + } + + /// + /// Deserialize the input JSON element to a WritableSubResource object. + /// + /// The JSON element to be deserialized. + /// Deserialized WritableSubResource object. + internal static WritableSubResource DeserializeWritableSubResource(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + ResourceIdentifier id = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id")) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + id = new ResourceIdentifier(property.Value.GetString()); + continue; + } + } + return new WritableSubResource(id); + } + + private struct WritableSubResourceProperties + { + public ResourceIdentifier Id { get; set; } + } + + WritableSubResource IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeWritableSubResource(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref WritableSubResourceProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("id"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Id = new ResourceIdentifier(reader.GetString()); + return; + } + reader.Skip(); + } + + WritableSubResource IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeWritableSubResource(doc.RootElement, options); + } + + internal partial class WritableSubResourceConverter : JsonConverter + { + public override void Write(Utf8JsonWriter writer, WritableSubResource model, JsonSerializerOptions options) + { + writer.WriteObjectValue(model); + } + public override WritableSubResource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using var document = JsonDocument.ParseValue(ref reader); + return DeserializeWritableSubResource(document.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.cs new file mode 100644 index 000000000000..2267f1e23685 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// + /// A class representing a sub-resource that contains only the ID. + /// + public partial class WritableSubResource + { + /// + /// Initializes an empty instance of for mocking. + /// + public WritableSubResource() + { + } + + /// Initializes a new instance of . + /// ARM resource Id. + protected internal WritableSubResource(ResourceIdentifier id) + { + Id = id; + } + + /// + /// Gets or sets the ARM resource identifier. + /// + /// + public ResourceIdentifier Id { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.Serialization.cs new file mode 100644 index 000000000000..2eb8fe97b0b1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.Serialization.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ZoneMapping : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ZoneMapping DeserializeZoneMapping(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional location = default; + Optional> zones = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("location"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + location = new AzureLocation(property.Value.GetString()); + continue; + } + if (property.NameEquals("zones"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + zones = array; + continue; + } + } + return new ZoneMapping(Optional.ToNullable(location), Optional.ToList(zones)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Location)) + { + writer.WritePropertyName("location"u8); + writer.WriteStringValue(Location.Value.DisplayName); + } + if (Optional.IsCollectionDefined(Zones)) + { + writer.WritePropertyName("zones"u8); + writer.WriteStartArray(); + foreach (var item in Zones) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + writer.WriteEndObject(); + } + + private struct ZoneMappingProperties + { + public Optional Location { get; set; } + public Optional> Zones { get; set; } + } + + ZoneMapping IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeZoneMapping(doc.RootElement, options); + } + + ZoneMapping IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeZoneMapping(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.cs new file mode 100644 index 000000000000..40f58aaf7f9f --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The ZoneMapping. + public partial class ZoneMapping + { + /// Initializes a new instance of ZoneMapping. + internal ZoneMapping() + { + Zones = new ChangeTrackingList(); + } + + /// Initializes a new instance of ZoneMapping. + /// The location of the zone mapping. + /// + internal ZoneMapping(AzureLocation? location, IReadOnlyList zones) + { + Location = location; + Zones = zones; + } + + /// The location of the zone mapping. + public AzureLocation? Location { get; } + /// Gets the zones. + public IReadOnlyList Zones { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetData.json b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetData.json new file mode 100644 index 000000000000..0081d88bbfbe --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetData.json @@ -0,0 +1,16 @@ +{ + "name": "testAS-3375", + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", + "type": "Microsoft.Compute/availabilitySets", + "location": "eastus", + "tags": { + "key": "value" + }, + "properties": { + "platformUpdateDomainCount": 5, + "platformFaultDomainCount": 3 + }, + "sku": { + "name": "Classic" + } +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWireFormat.json b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWireFormat.json new file mode 100644 index 000000000000..fc1edd16647e --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWireFormat.json @@ -0,0 +1,18 @@ +{ + "name": "testAS-3375", + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", + "type": "Microsoft.Compute/availabilitySets", + "location": "eastus", + "tags": { + "key": "value" + }, + "properties": { + "platformUpdateDomainCount": 5, + "platformFaultDomainCount": 3 + }, + "sku": { + "name": "Classic" + }, + "extraSku": "extraSku", + "extraRoot": "extraRoot" +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWithVMs.json b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWithVMs.json new file mode 100644 index 000000000000..173cb7ae02fe --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWithVMs.json @@ -0,0 +1,24 @@ +{ + "name": "testAS-3375", + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", + "type": "Microsoft.Compute/availabilitySets", + "location": "eastus", + "tags": { + "key": "value" + }, + "properties": { + "platformUpdateDomainCount": 5, + "platformFaultDomainCount": 3, + "virtualMachines": [ + { + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS1" + }, + { + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS2" + } + ] + }, + "sku": { + "name": "Classic" + } +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWithVMsWireFormat.json b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWithVMsWireFormat.json new file mode 100644 index 000000000000..173cb7ae02fe --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData/AvailabilitySetDataWithVMsWireFormat.json @@ -0,0 +1,24 @@ +{ + "name": "testAS-3375", + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", + "type": "Microsoft.Compute/availabilitySets", + "location": "eastus", + "tags": { + "key": "value" + }, + "properties": { + "platformUpdateDomainCount": 5, + "platformFaultDomainCount": 3, + "virtualMachines": [ + { + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS1" + }, + { + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS2" + } + ] + }, + "sku": { + "name": "Classic" + } +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/ModelX/ModelX.json b/sdk/core/Azure.Core/tests/common/TestData/ModelX/ModelX.json new file mode 100644 index 000000000000..308a552bea92 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ModelX/ModelX.json @@ -0,0 +1,13 @@ +{ + "kind": "X", + "name": "xmodel", + "xProperty": 100, + "fields": [ + "testField" + ], + "nullProperty": null, + "keyValuePairs": { + "color": "red" + }, + "extra": "stuff" +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/ModelX/ModelXWireFormat.json b/sdk/core/Azure.Core/tests/common/TestData/ModelX/ModelXWireFormat.json new file mode 100644 index 000000000000..3c8f056c3eca --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ModelX/ModelXWireFormat.json @@ -0,0 +1,13 @@ +{ + "kind": "X", + "name": "xmodel", + "xProperty": 100, + "fields": [ + "testField" + ], + "nullProperty": null, + "keyValuePairs": { + "color": "red" + }, + "extra": "stuff" +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/ModelXml.xml b/sdk/core/Azure.Core/tests/common/TestData/ModelXml.xml new file mode 100644 index 000000000000..2d6c52e2cc82 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ModelXml.xml @@ -0,0 +1,9 @@ + + Color + Red + ReadOnly + + ChildRed + ChildReadOnly + + diff --git a/sdk/core/Azure.Core/tests/common/TestData/ModelXmlX.xml b/sdk/core/Azure.Core/tests/common/TestData/ModelXmlX.xml new file mode 100644 index 000000000000..a6c7329e21d8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ModelXmlX.xml @@ -0,0 +1,9 @@ + + Color + Red + ReadOnly + + ChildRed + ChildReadOnly + + diff --git a/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData/ResourceProviderData-Collapsed.json b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData/ResourceProviderData-Collapsed.json new file mode 100644 index 000000000000..174ff6cdbe4d --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData/ResourceProviderData-Collapsed.json @@ -0,0 +1 @@ +{"id":"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/providers/Microsoft.Network","namespace":"Microsoft.Network","resourceTypes":[{"resourceType":"virtualNetworks","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"virtualNetworks/taggedTrafficConsumers","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"natGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"publicIPAddresses","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"internalPublicIpAddresses","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01"],"capabilities":"None"},{"resourceType":"customIpPrefixes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01"],"defaultApiVersion":"2020-06-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkInterfaces","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dscpConfigurations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01"],"defaultApiVersion":"2020-06-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateEndpoints","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"defaultApiVersion":"2020-03-01","locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateEndpoints/privateLinkServiceProxies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"defaultApiVersion":"2020-03-01","capabilities":"None"},{"resourceType":"privateEndpointRedirectMaps","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"loadBalancers","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkSecurityGroups","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"applicationSecurityGroups","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2017-09-01"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"serviceEndpointPolicies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkIntentPolicies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"routeTables","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"publicIPPrefixes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers/connectionMonitors","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers/flowLogs","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers/pingMeshes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"virtualNetworkGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-03-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"localNetworkGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-03-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"connections","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-03-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"applicationGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"applicationGatewayWebApplicationFirewallPolicies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"locations","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/operations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/operationResults","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/CheckDnsNameAvailability","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"capabilities":"None"},{"resourceType":"locations/setLoadBalancerFrontendPublicIpAddresses","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01"],"capabilities":"None"},{"resourceType":"cloudServiceSlots","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01"],"capabilities":"SupportsExtension"},{"resourceType":"locations/usages","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/virtualNetworkAvailableEndpointServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01"],"capabilities":"None"},{"resourceType":"locations/availableDelegations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/ApplicationGatewayWafDynamicManifests","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01"],"capabilities":"None"},{"resourceType":"locations/serviceTags","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"capabilities":"None"},{"resourceType":"locations/availablePrivateEndpointTypes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"capabilities":"None"},{"resourceType":"locations/availableServiceAliases","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01"],"capabilities":"None"},{"resourceType":"locations/checkPrivateLinkServiceVisibility","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01"],"capabilities":"None"},{"resourceType":"locations/autoApprovedPrivateLinkServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01"],"capabilities":"None"},{"resourceType":"locations/batchValidatePrivateEndpointsForResourceMove","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"capabilities":"None"},{"resourceType":"locations/batchNotifyPrivateEndpointsForResourceMove","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"capabilities":"None"},{"resourceType":"locations/supportedVirtualMachineSizes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/setAzureNetworkManagerConfiguration","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01"],"capabilities":"None"},{"resourceType":"locations/publishResources","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01"],"capabilities":"None"},{"resourceType":"locations/getAzureNetworkManagerConfiguration","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01"],"capabilities":"None"},{"resourceType":"locations/checkAcceleratedNetworkingSupport","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/validateResourceOwnership","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/setResourceOwnership","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/effectiveResourceOwnership","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"operations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"capabilities":"None"},{"resourceType":"dnszones","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2016-04-01"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2016-04-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2016-04-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsOperationResults","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnsOperationStatuses","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"getDnsResourceReference","locations":["global"],"apiVersions":["2018-05-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"internalNotify","locations":["global"],"apiVersions":["2018-05-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/A","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/AAAA","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/CNAME","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/PTR","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/MX","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/TXT","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/SRV","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/SOA","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/NS","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/CAA","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/recordsets","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/all","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"privateDnsZones","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateDnsZones/virtualNetworkLinks","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateDnsOperationResults","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsOperationStatuses","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZonesInternal","locations":["global"],"apiVersions":["2020-06-01","2020-01-01"],"defaultApiVersion":"2020-01-01","capabilities":"None"},{"resourceType":"privateDnsZones/A","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/AAAA","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/CNAME","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/PTR","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/MX","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/TXT","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/SRV","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/SOA","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/all","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"virtualNetworks/privateDnsZoneLinks","locations":["global"],"apiVersions":["2020-06-01"],"defaultApiVersion":"2020-06-01","capabilities":"None"},{"resourceType":"dnsResolvers","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsResolvers/inboundEndpoints","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsResolvers/outboundEndpoints","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsForwardingRulesets","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsForwardingRulesets/forwardingRules","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"dnsForwardingRulesets/virtualNetworkLinks","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"virtualNetworks/listDnsResolvers","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"virtualNetworks/listDnsForwardingRulesets","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"locations/dnsResolverOperationResults","locations":[],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"locations/dnsResolverOperationStatuses","locations":[],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"trafficmanagerprofiles","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"trafficmanagerprofiles/heatMaps","locations":["global"],"apiVersions":["2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-09-01-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficmanagerprofiles/azureendpoints","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficmanagerprofiles/externalendpoints","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficmanagerprofiles/nestedendpoints","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"checkTrafficManagerNameAvailability","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"checkTrafficManagerNameAvailabilityV2","locations":["global"],"apiVersions":["2022-12-01-preview"],"defaultApiVersion":"2022-12-01-preview","capabilities":"None"},{"resourceType":"trafficManagerUserMetricsKeys","locations":["global"],"apiVersions":["2022-04-01-preview","2018-08-01","2018-04-01","2017-09-01-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficManagerGeographicHierarchies","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"expressRouteCircuits","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"expressRouteServiceProviders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableWafRuleSets","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableSslOptions","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableServerVariables","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableRequestHeaders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableResponseHeaders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"capabilities":"None"},{"resourceType":"routeFilters","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"bgpServiceCommunities","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01"],"capabilities":"None"},{"resourceType":"virtualWans","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"vpnSites","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"vpnServerConfigurations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","South Africa North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"virtualHubs","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"vpnGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"p2sVpnGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","UAE North","South Africa North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"expressRouteGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"locations/hybridEdgeZone","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01"],"capabilities":"None"},{"resourceType":"expressRoutePortsLocations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"capabilities":"None"},{"resourceType":"expressRoutePorts","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","UAE North","South Africa North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"firewallPolicies","locations":["Qatar Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Brazil Southeast","West US 3","Jio India West","Sweden Central","Japan East","UK West","West US","East US","North Europe","West Europe","West Central US","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01"],"defaultApiVersion":"2020-04-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"ipGroups","locations":["Qatar Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Brazil Southeast","West US 3","Jio India West","Sweden Central","Japan East","UK West","West US","East US","North Europe","West Europe","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","West Central US","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01"],"defaultApiVersion":"2020-04-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"azureWebCategories","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01"],"defaultApiVersion":"2020-08-01","capabilities":"None"},{"resourceType":"locations/nfvOperations","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"capabilities":"None"},{"resourceType":"locations/nfvOperationResults","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"capabilities":"None"},{"resourceType":"securityPartnerProviders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"azureFirewalls","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","France Central","Australia Central","Japan West","Japan East","Korea Central","Korea South","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"azureFirewallFqdnTags","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"capabilities":"None"},{"resourceType":"virtualNetworkTaps","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"privateLinkServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"locations/privateLinkServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"capabilities":"None"},{"resourceType":"ddosProtectionPlans","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2018-02-01"}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"networkProfiles","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"checkFrontdoorNameAvailability","locations":["global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoorWebApplicationFirewallManagedRuleSets","locations":["global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2022-05-01","2020-11-01","2020-04-01","2019-10-01","2019-03-01"],"defaultApiVersion":"2020-11-01","capabilities":"None"},{"resourceType":"locations/bareMetalTenants","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01"],"capabilities":"None"},{"resourceType":"bastionHosts","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"virtualRouters","locations":["Qatar Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Brazil Southeast","West US 3","Jio India West","Sweden Central","Japan East","UK West","West US","East US","North Europe","West Europe","West Central US","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01"],"defaultApiVersion":"2020-04-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"networkVirtualAppliances","locations":["Qatar Central","Brazil Southeast","West US 3","Jio India West","Sweden Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Japan East","UK West","West US","East US","North Europe","West Europe","West Central US","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01"],"defaultApiVersion":"2020-04-01","capabilities":"SystemAssignedResourceIdentity, SupportsTags, SupportsLocation"},{"resourceType":"ipAllocations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkManagers","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkManagerConnections","locations":[],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"SupportsExtension"},{"resourceType":"locations/queryNetworkSecurityPerimeter","locations":["West Central US","Jio India West","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2022-02-01-preview","2021-05-01-preview","2021-02-01-preview"],"defaultApiVersion":"2021-02-01-preview","capabilities":"None"},{"resourceType":"virtualNetworks/listNetworkManagerEffectiveConnectivityConfigurations","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"None"},{"resourceType":"virtualNetworks/listNetworkManagerEffectiveSecurityAdminRules","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"None"},{"resourceType":"networkGroupMemberships","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2022-06-01-preview"],"defaultApiVersion":"2022-06-01-preview","capabilities":"SupportsExtension"},{"resourceType":"locations/commitInternalAzureNetworkManagerConfiguration","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"capabilities":"None"},{"resourceType":"locations/internalAzureVirtualNetworkManagerOperation","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"capabilities":"None"},{"resourceType":"networkVirtualApplianceSkus","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"defaultApiVersion":"2020-04-01","capabilities":"None"},{"resourceType":"locations/serviceTagDetails","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01"],"capabilities":"None"},{"resourceType":"locations/dataTasks","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01"],"capabilities":"None"},{"resourceType":"networkWatchers/lenses","locations":["Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"frontdoorOperationResults","locations":["global"],"apiVersions":["2022-05-01","2021-06-01","2020-11-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-11-01","2019-10-01","2019-08-01","2019-05-01","2019-04-01","2019-03-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoors","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"frontdoors/frontendEndpoints","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoors/frontendEndpoints/customHttpsConfiguration","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoorWebApplicationFirewallPolicies","locations":["East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2022-05-01","2020-11-01","2020-04-01","2019-10-01","2019-03-01","2018-08-01"],"defaultApiVersion":"2020-11-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"networkExperimentProfiles","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","West US 2","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2019-11-01"],"defaultApiVersion":"2019-11-01","capabilities":"SupportsTags, SupportsLocation"}],"registrationState":"Registered","registrationPolicy":"RegistrationRequired"} diff --git a/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData/ResourceProviderData.json b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData/ResourceProviderData.json new file mode 100644 index 000000000000..5e95ddfd70d2 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData/ResourceProviderData.json @@ -0,0 +1,11392 @@ +{ + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/providers/Microsoft.Network", + "namespace": "Microsoft.Network", + "resourceTypes": [ + { + "resourceType": "virtualNetworks", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualNetworks/taggedTrafficConsumers", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "natGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "publicIPAddresses", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "internalPublicIpAddresses", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "customIpPrefixes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01" + ], + "defaultApiVersion": "2020-06-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkInterfaces", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dscpConfigurations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01" + ], + "defaultApiVersion": "2020-06-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateEndpoints", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "defaultApiVersion": "2020-03-01", + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateEndpoints/privateLinkServiceProxies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "None" + }, + { + "resourceType": "privateEndpointRedirectMaps", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "loadBalancers", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkSecurityGroups", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "applicationSecurityGroups", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2017-09-01" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "serviceEndpointPolicies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkIntentPolicies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "routeTables", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "publicIPPrefixes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers/connectionMonitors", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers/flowLogs", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers/pingMeshes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualNetworkGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-03-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "localNetworkGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-03-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "connections", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-03-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "applicationGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "applicationGatewayWebApplicationFirewallPolicies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "locations", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/operations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/operationResults", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/CheckDnsNameAvailability", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/setLoadBalancerFrontendPublicIpAddresses", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01" + ], + "capabilities": "None" + }, + { + "resourceType": "cloudServiceSlots", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01" + ], + "capabilities": "SupportsExtension" + }, + { + "resourceType": "locations/usages", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/virtualNetworkAvailableEndpointServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/availableDelegations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/ApplicationGatewayWafDynamicManifests", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/serviceTags", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/availablePrivateEndpointTypes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/availableServiceAliases", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/checkPrivateLinkServiceVisibility", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/autoApprovedPrivateLinkServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/batchValidatePrivateEndpointsForResourceMove", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/batchNotifyPrivateEndpointsForResourceMove", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/supportedVirtualMachineSizes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/setAzureNetworkManagerConfiguration", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/publishResources", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/getAzureNetworkManagerConfiguration", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/checkAcceleratedNetworkingSupport", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/validateResourceOwnership", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/setResourceOwnership", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/effectiveResourceOwnership", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "operations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "capabilities": "None" + }, + { + "resourceType": "dnszones", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2016-04-01" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2016-04-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2016-04-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsOperationResults", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnsOperationStatuses", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "getDnsResourceReference", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "internalNotify", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/A", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/AAAA", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/CNAME", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/PTR", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/MX", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/TXT", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/SRV", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/SOA", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/NS", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/CAA", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/recordsets", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/all", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateDnsZones/virtualNetworkLinks", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateDnsOperationResults", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsOperationStatuses", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZonesInternal", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01" + ], + "defaultApiVersion": "2020-01-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/A", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/AAAA", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/CNAME", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/PTR", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/MX", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/TXT", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/SRV", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/SOA", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/all", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/privateDnsZoneLinks", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01" + ], + "defaultApiVersion": "2020-06-01", + "capabilities": "None" + }, + { + "resourceType": "dnsResolvers", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsResolvers/inboundEndpoints", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsResolvers/outboundEndpoints", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsForwardingRulesets", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsForwardingRulesets/forwardingRules", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "dnsForwardingRulesets/virtualNetworkLinks", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listDnsResolvers", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listDnsForwardingRulesets", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "locations/dnsResolverOperationResults", + "locations": [], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "locations/dnsResolverOperationStatuses", + "locations": [], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "trafficmanagerprofiles/heatMaps", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-09-01-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles/azureendpoints", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles/externalendpoints", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles/nestedendpoints", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "checkTrafficManagerNameAvailability", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "checkTrafficManagerNameAvailabilityV2", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview" + ], + "defaultApiVersion": "2022-12-01-preview", + "capabilities": "None" + }, + { + "resourceType": "trafficManagerUserMetricsKeys", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2017-09-01-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficManagerGeographicHierarchies", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "expressRouteCircuits", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "expressRouteServiceProviders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableWafRuleSets", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableSslOptions", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableServerVariables", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableRequestHeaders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableResponseHeaders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "capabilities": "None" + }, + { + "resourceType": "routeFilters", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "bgpServiceCommunities", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01" + ], + "capabilities": "None" + }, + { + "resourceType": "virtualWans", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "vpnSites", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "vpnServerConfigurations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "South Africa North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualHubs", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "vpnGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "p2sVpnGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "UAE North", + "South Africa North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "expressRouteGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "locations/hybridEdgeZone", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "expressRoutePortsLocations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "expressRoutePorts", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "UAE North", + "South Africa North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "firewallPolicies", + "locations": [ + "Qatar Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "West Central US", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "ipGroups", + "locations": [ + "Qatar Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "West Central US", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "azureWebCategories", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01" + ], + "defaultApiVersion": "2020-08-01", + "capabilities": "None" + }, + { + "resourceType": "locations/nfvOperations", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/nfvOperationResults", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "capabilities": "None" + }, + { + "resourceType": "securityPartnerProviders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "azureFirewalls", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "France Central", + "Australia Central", + "Japan West", + "Japan East", + "Korea Central", + "Korea South", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "azureFirewallFqdnTags", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "virtualNetworkTaps", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateLinkServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "locations/privateLinkServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "ddosProtectionPlans", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2018-02-01" + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkProfiles", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "checkFrontdoorNameAvailability", + "locations": [ + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoorWebApplicationFirewallManagedRuleSets", + "locations": [ + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2022-05-01", + "2020-11-01", + "2020-04-01", + "2019-10-01", + "2019-03-01" + ], + "defaultApiVersion": "2020-11-01", + "capabilities": "None" + }, + { + "resourceType": "locations/bareMetalTenants", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01" + ], + "capabilities": "None" + }, + { + "resourceType": "bastionHosts", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualRouters", + "locations": [ + "Qatar Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "West Central US", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkVirtualAppliances", + "locations": [ + "Qatar Central", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "West Central US", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SystemAssignedResourceIdentity, SupportsTags, SupportsLocation" + }, + { + "resourceType": "ipAllocations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkManagers", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkManagerConnections", + "locations": [], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "SupportsExtension" + }, + { + "resourceType": "locations/queryNetworkSecurityPerimeter", + "locations": [ + "West Central US", + "Jio India West", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2022-02-01-preview", + "2021-05-01-preview", + "2021-02-01-preview" + ], + "defaultApiVersion": "2021-02-01-preview", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listNetworkManagerEffectiveConnectivityConfigurations", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listNetworkManagerEffectiveSecurityAdminRules", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "None" + }, + { + "resourceType": "networkGroupMemberships", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2022-06-01-preview" + ], + "defaultApiVersion": "2022-06-01-preview", + "capabilities": "SupportsExtension" + }, + { + "resourceType": "locations/commitInternalAzureNetworkManagerConfiguration", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/internalAzureVirtualNetworkManagerOperation", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "networkVirtualApplianceSkus", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "None" + }, + { + "resourceType": "locations/serviceTagDetails", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/dataTasks", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "networkWatchers/lenses", + "locations": [ + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "frontdoorOperationResults", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-05-01", + "2021-06-01", + "2020-11-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-11-01", + "2019-10-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2019-03-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoors", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "frontdoors/frontendEndpoints", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoors/frontendEndpoints/customHttpsConfiguration", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoorWebApplicationFirewallPolicies", + "locations": [ + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2022-05-01", + "2020-11-01", + "2020-04-01", + "2019-10-01", + "2019-03-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-11-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkExperimentProfiles", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "West US 2", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2019-11-01" + ], + "defaultApiVersion": "2019-11-01", + "capabilities": "SupportsTags, SupportsLocation" + } + ], + "registrationState": "Registered", + "registrationPolicy": "RegistrationRequired" +} diff --git a/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj b/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj index 12fa5a7a43f6..b72322330177 100644 --- a/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj +++ b/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj @@ -22,6 +22,7 @@ + diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTests.cs new file mode 100644 index 000000000000..d350351a0912 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTests.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ResourceManager.Compute; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class AvailabilitySetDataTests : ModelJsonTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("AvailabilitySetData/AvailabilitySetDataWireFormat.json")).TrimEnd(); + + protected override string JsonPayload => WirePayload; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (AvailabilitySetData)response; + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + var expectedSerializedString = "{"; + if (format == ModelSerializerFormat.Json) + expectedSerializedString += "\"name\":\"testAS-3375\",\"id\":\"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375\",\"type\":\"Microsoft.Compute/availabilitySets\","; + expectedSerializedString += "\"sku\":{\"name\":\"Classic\""; + //if (!ignoreAdditionalProperties) + // expectedSerializedString += ",\"extraSku\":\"extraSku\""; + expectedSerializedString += "},\"tags\":{\"key\":\"value\"},\"location\":\"eastus\",\"properties\":{\"platformUpdateDomainCount\":5,\"platformFaultDomainCount\":3}"; + //if (!ignoreAdditionalProperties) + // expectedSerializedString += ",\"extraRoot\":\"extraRoot\""; + expectedSerializedString += "}"; + return expectedSerializedString; ; + } + + protected override void VerifyModel(AvailabilitySetData model, ModelSerializerFormat format) + { + Dictionary expectedTags = new Dictionary() { { "key", "value" } }; + + Assert.AreEqual("/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", model.Id.ToString()); + CollectionAssert.AreEquivalent(expectedTags, model.Tags); + Assert.AreEqual(AzureLocation.EastUS, model.Location); + Assert.AreEqual("testAS-3375", model.Name); + Assert.AreEqual("Microsoft.Compute/availabilitySets", model.ResourceType.ToString()); + Assert.AreEqual(5, model.PlatformUpdateDomainCount); + Assert.AreEqual(3, model.PlatformFaultDomainCount); + Assert.AreEqual("Classic", model.Sku.Name); + } + + protected override void CompareModels(AvailabilitySetData model, AvailabilitySetData model2, ModelSerializerFormat format) + { + Assert.AreEqual(format == ModelSerializerFormat.Wire ? null : model.Id, model2.Id); + Assert.AreEqual(model.Location, model2.Location); + Assert.AreEqual(format == ModelSerializerFormat.Wire ? null : model.Name, model2.Name); + Assert.AreEqual(model.PlatformFaultDomainCount, model2.PlatformFaultDomainCount); + Assert.AreEqual(model.PlatformUpdateDomainCount, model2.PlatformUpdateDomainCount); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual(model.ResourceType, model2.ResourceType); + CollectionAssert.AreEquivalent(model.Tags, model2.Tags); + Assert.AreEqual(model.Sku.Name, model2.Sku.Name); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTestsWithVMs.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTestsWithVMs.cs new file mode 100644 index 000000000000..26e1624a1eb4 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTestsWithVMs.cs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ResourceManager.Compute; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class AvailabilitySetDataTestsWithVMs : ModelJsonTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("AvailabilitySetData/AvailabilitySetDataWithVMsWireFormat.json")).TrimEnd(); + + protected override string JsonPayload => WirePayload; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (AvailabilitySetData)response; + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + var expectedSerializedString = "{"; + if (format == ModelSerializerFormat.Json) + expectedSerializedString += "\"name\":\"testAS-3375\",\"id\":\"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375\",\"type\":\"Microsoft.Compute/availabilitySets\","; + expectedSerializedString += "\"sku\":{\"name\":\"Classic\""; + //if (!ignoreAdditionalProperties) + // expectedSerializedString += ",\"extraSku\":\"extraSku\""; + expectedSerializedString += "},\"tags\":{\"key\":\"value\"},\"location\":\"eastus\",\"properties\":{\"platformUpdateDomainCount\":5,\"platformFaultDomainCount\":3"; + //if (!ignoreAdditionalProperties) + // expectedSerializedString += ",\"extraRoot\":\"extraRoot\""; + expectedSerializedString += ",\"virtualMachines\":[{\"id\":\"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS1\"},{\"id\":\"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS2\"}]"; + expectedSerializedString += "}}"; + return expectedSerializedString; ; + } + + protected override void VerifyModel(AvailabilitySetData model, ModelSerializerFormat format) + { + Dictionary expectedTags = new Dictionary() { { "key", "value" } }; + + Assert.AreEqual("/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", model.Id.ToString()); + CollectionAssert.AreEquivalent(expectedTags, model.Tags); + Assert.AreEqual(AzureLocation.EastUS, model.Location); + Assert.AreEqual("testAS-3375", model.Name); + Assert.AreEqual("Microsoft.Compute/availabilitySets", model.ResourceType.ToString()); + Assert.AreEqual(5, model.PlatformUpdateDomainCount); + Assert.AreEqual(3, model.PlatformFaultDomainCount); + Assert.AreEqual("Classic", model.Sku.Name); + Assert.AreEqual(2, model.VirtualMachines.Count); + Assert.AreEqual("/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS1", model.VirtualMachines[0].Id.ToString()); + Assert.AreEqual("/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS2", model.VirtualMachines[1].Id.ToString()); + } + + protected override void CompareModels(AvailabilitySetData model, AvailabilitySetData model2, ModelSerializerFormat format) + { + Assert.AreEqual(format == ModelSerializerFormat.Wire ? null : model.Id, model2.Id); + Assert.AreEqual(model.Location, model2.Location); + Assert.AreEqual(format == ModelSerializerFormat.Wire ? null : model.Name, model2.Name); + Assert.AreEqual(model.PlatformFaultDomainCount, model2.PlatformFaultDomainCount); + Assert.AreEqual(model.PlatformUpdateDomainCount, model2.PlatformUpdateDomainCount); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual(model.ResourceType, model2.ResourceType); + CollectionAssert.AreEquivalent(model.Tags, model2.Tags); + Assert.AreEqual(model.Sku.Name, model2.Sku.Name); + Assert.AreEqual(model.VirtualMachines.Count, model2.VirtualMachines.Count); + Assert.AreEqual(model.VirtualMachines[0].Id, model2.VirtualMachines[0].Id); + Assert.AreEqual(model.VirtualMachines[1].Id, model2.VirtualMachines[1].Id); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/BaseModelTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/BaseModelTests.cs new file mode 100644 index 000000000000..8ffd4e4b6db7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/BaseModelTests.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Linq; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class BaseModelTests : ModelJsonTests + { + protected override BaseModel GetModelInstance() + { + var typeToActivate = typeof(BaseModel).Assembly.GetTypes().FirstOrDefault(t => t.Name == $"Unknown{typeof(BaseModel).Name}"); + return Activator.CreateInstance(typeToActivate, true) as BaseModel; + } + + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"kind\":\"X\",\"name\":\"xmodel\",\"xProperty\":100,\"extra\":\"stuff\"}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (BaseModel)response; + + protected override void CompareModels(BaseModel model, BaseModel model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Name, model2.Name); + Assert.AreEqual(model.Kind, model2.Kind); + if (format == ModelSerializerFormat.Json) + { + var rawData = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData); + Assert.IsNotNull(rawData2); + Assert.AreEqual(rawData.Count, rawData2.Count); + Assert.AreEqual(rawData["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"kind\":\"X\",\"name\":\"xmodel\""; + if (format == ModelSerializerFormat.Json) + expected += ",\"xProperty\":100"; + if (format == ModelSerializerFormat.Json) + expected += ",\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(BaseModel model, ModelSerializerFormat format) + { + Assert.AreEqual("X", model.Kind); + Assert.AreEqual("xmodel", model.Name); + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/EnvelopeTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/EnvelopeTests.cs new file mode 100644 index 000000000000..c7b8535e1174 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/EnvelopeTests.cs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text; +using Azure.Core.Serialization; +using Newtonsoft.Json; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class EnvelopeTests : ModelJsonTests> + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"readOnlyProperty\":\"read\"," + + "\"modelA\":{\"name\":\"Cat\",\"isHungry\":false,\"weight\":2.5}," + + "\"modelC\":{\"x\":\"hello\",\"y\":\"bye\"}" + + "}"; + + protected override Func, RequestContent> ToRequestContent => model => model; + + protected override Func> FromResponse => response => (Envelope)response; + + protected override Func GetObjectSerializerFactory(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + JsonSerializerSettings settings = new JsonSerializerSettings + { + ContractResolver = new IgnoreReadOnlyPropertiesResolver() + }; + return type => type.Equals(typeof(ModelC)) ? new NewtonsoftJsonObjectSerializer(settings) : null; + } + else + { + return type => type.Equals(typeof(ModelC)) ? new NewtonsoftJsonObjectSerializer() : null; + } + } + + protected override void CompareModels(Envelope model, Envelope model2, ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.ModelA.LatinName, model2.ModelA.LatinName); + Assert.AreEqual(model.ModelA.HasWhiskers, model2.ModelA.HasWhiskers); + } + Assert.AreEqual(model.ModelA.Name, model2.ModelA.Name); + Assert.AreEqual(model.ModelA.IsHungry, model2.ModelA.IsHungry); + Assert.AreEqual(model.ModelA.Weight, model2.ModelA.Weight); + Assert.AreEqual(model.ModelT.X, model2.ModelT.X); + Assert.AreEqual(model.ModelT.Y, model2.ModelT.Y); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + StringBuilder expectedSerialized = new StringBuilder("{"); + if (format == ModelSerializerFormat.Json) + { + expectedSerialized.Append("\"readOnlyProperty\":\"read\","); + } + expectedSerialized.Append("\"modelA\":{"); + if (format == ModelSerializerFormat.Json) + { + expectedSerialized.Append("\"latinName\":\"Felis catus\",\"hasWhiskers\":false,"); + } + expectedSerialized.Append("\"name\":\"Cat\",\"isHungry\":false,\"weight\":2.5},"); + expectedSerialized.Append("\"modelC\":{\"X\":\"hello\",\"Y\":\"bye\"}"); //using NewtonSoft Serializer + expectedSerialized.Append("}"); + return expectedSerialized.ToString(); + } + + protected override void VerifyModel(Envelope model, ModelSerializerFormat format) + { + Assert.IsNotNull(model.ModelA); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual("read", model.ReadOnlyProperty); + Assert.AreEqual("Felis catus", model.ModelA.LatinName); + Assert.AreEqual(false, model.ModelA.HasWhiskers); + } + Assert.AreEqual("Cat", model.ModelA.Name); + Assert.AreEqual(false, model.ModelA.IsHungry); + Assert.AreEqual(2.5, model.ModelA.Weight); + Assert.IsNotNull(model.ModelT); + Assert.AreEqual("hello", model.ModelT.X); + Assert.AreEqual("bye", model.ModelT.Y); + } + + // Generate a class that implements the NewtonSoft default contract resolver so that ReadOnly properties are not serialized + // This is used to verify that the ReadOnly properties are not serialized when IgnoreReadOnlyProperties is set to true + private class IgnoreReadOnlyPropertiesResolver : Newtonsoft.Json.Serialization.DefaultContractResolver + { + protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, MemberSerialization memberSerialization) + { + Newtonsoft.Json.Serialization.JsonProperty property = base.CreateProperty(member, memberSerialization); + + if (!property.Writable) + { + property.ShouldSerialize = obj => false; + } + + return property; + } + } + + public class ModelC + { + public ModelC(string x1, string y1) + { + X = x1; + Y = y1; + } + + public string X { get; set; } + public string Y { get; set; } + + public static void VerifyModelC(ModelC c1, ModelC c2) + { + Assert.That(c1.X == c2.X); + Assert.That(c1.Y == c2.Y); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelAsStructTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelAsStructTests.cs new file mode 100644 index 000000000000..29e3cdd85a42 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelAsStructTests.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelAsStructTests : ModelJsonTests + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"id\":5,\"extra\":\"stuff\"}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelAsStruct)response; + + protected override void CompareModels(ModelAsStruct model, ModelAsStruct model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Id, model2.Id); + var rawData1 = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData1); + Assert.IsNotNull(rawData2); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual(rawData1["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"id\":5"; + if (format == ModelSerializerFormat.Json) + expected += ",\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(ModelAsStruct model, ModelSerializerFormat format) + { + Assert.AreEqual(5, model.Id); + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelJsonTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelJsonTests.cs new file mode 100644 index 000000000000..6a9488ec32e1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelJsonTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Serialization; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal abstract class ModelJsonTests : ModelTests where T : IModelJsonSerializable + { + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceOfT(string format) + => RoundTripTest(format, new JsonInterfaceStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceNonGeneric(string format) + => RoundTripTest(format, new JsonInterfaceNonGenericStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceUtf8Reader(string format) + => RoundTripTest(format, new JsonInterfaceUtf8ReaderStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceUtf8ReaderNonGeneric(string format) + => RoundTripTest(format, new JsonInterfaceUtf8ReaderNonGenericStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelJsonConverter(string format) + => RoundTripTest(format, new ModelJsonConverterStrategy()); + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelTests.cs new file mode 100644 index 000000000000..9a9bf45f5041 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelTests.cs @@ -0,0 +1,228 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Azure.Core.Serialization; +using Microsoft.Extensions.Options; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public abstract class ModelTests where T : IModelSerializable + { + private T _modelInstance; + private T ModelInstance => _modelInstance ??= GetModelInstance(); + + private bool IsXmlWireFormat => WirePayload.StartsWith("<", StringComparison.Ordinal); + + protected virtual T GetModelInstance() + { + return (T)Activator.CreateInstance(typeof(T), true); + } + + protected abstract string GetExpectedResult(ModelSerializerFormat format); + protected abstract void VerifyModel(T model, ModelSerializerFormat format); + protected abstract void CompareModels(T model, T model2, ModelSerializerFormat format); + protected abstract string JsonPayload { get; } + protected abstract string WirePayload { get; } + protected abstract Func ToRequestContent { get; } + protected abstract Func FromResponse { get; } + + protected virtual Func GetObjectSerializerFactory(ModelSerializerFormat format) => null; + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelSerializer(string format) + => RoundTripTest(format, new ModelSerializerStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelSerializerNonGeneric(string format) + => RoundTripTest(format, new ModelSerializerNonGenericStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelSerializerFormatOverload(string format) + { + //if we only pass in the format we can't test BYOM + if (!typeof(T).IsGenericType) + RoundTripTest(format, new ModelSerializerFormatOverloadStrategy()); + } + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelInterface(string format) + => RoundTripTest(format, new ModelInterfaceStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelInterfaceNonGeneric(string format) + => RoundTripTest(format, new ModelInterfaceNonGenericStrategy()); + + [Test] + public void RoundTripWithCast() + { + //cast does not work without options + if (!typeof(T).IsGenericType) + RoundTripTest(ModelSerializerFormat.Wire, new CastStrategy(ToRequestContent, FromResponse)); + } + + protected void RoundTripTest(ModelSerializerFormat format, RoundTripStrategy strategy) + { + string serviceResponse = format == ModelSerializerFormat.Json ? JsonPayload : WirePayload; + + ModelSerializerOptions options = new ModelSerializerOptions(format); + options.ObjectSerializerResolver = GetObjectSerializerFactory(format); + + var expectedSerializedString = GetExpectedResult(format); + + if (AssertFailures(strategy, format, serviceResponse, options)) + return; + + T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); + + VerifyModel(model, format); + var data = strategy.Serialize(model, options); + string roundTrip = data.ToString(); + + Assert.That(roundTrip, Is.EqualTo(expectedSerializedString)); + + T model2 = (T)strategy.Deserialize(roundTrip, ModelInstance, options); + CompareModels(model, model2, format); + } + + private bool AssertFailures(RoundTripStrategy strategy, ModelSerializerFormat format, string serviceResponse, ModelSerializerOptions options) + { + bool result = false; + if (IsXmlWireFormat && (strategy.IsExplicitJsonDeserialize || strategy.IsExplicitJsonSerialize) && format == ModelSerializerFormat.Wire) + { + if (strategy.IsExplicitJsonDeserialize) + { + if (strategy.GetType().Name.StartsWith("ModelJsonConverterStrategy")) + { + //we never get to the interface implementation because JsonSerializer errors before that + Assert.Throws(() => { T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); }); + result = true; + } + else + { + Assert.Throws(() => { T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); }); + result = true; + } + } + + if (strategy.IsExplicitJsonSerialize) + { + Assert.Throws(() => { var data = strategy.Serialize(ModelInstance, options); }); + result = true; + } + } + else if (ModelInstance is not IModelJsonSerializable && format == ModelSerializerFormat.Json) + { + Assert.Throws(() => { T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); }); + Assert.Throws(() => { var data = strategy.Serialize(ModelInstance, options); }); + result = true; + } + return result; + } + + internal static Dictionary GetRawData(object model) + { + Type modelType = model.GetType(); + while (modelType.BaseType != typeof(object) && modelType.BaseType != typeof(ValueType)) + { + modelType = modelType.BaseType; + } + var propertyInfo = modelType.GetField("_rawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); + return propertyInfo.GetValue(model) as Dictionary; + } + + [Test] + public void ThrowsIfUnknownFormat() + { + ModelSerializerOptions options = new ModelSerializerOptions("x"); + Assert.Throws(() => ModelSerializer.Serialize(ModelInstance, options)); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData("x"), options)); + + Assert.Throws(() => ModelSerializer.Serialize((IModelSerializable)ModelInstance, options)); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData("x"), typeof(T), options)); + if (ModelInstance is IModelJsonSerializable jsonModel) + { + Assert.Throws(() => jsonModel.Serialize(new Utf8JsonWriter(new MemoryStream()), options)); + Assert.Throws(() => ((IModelJsonSerializable)jsonModel).Serialize(new Utf8JsonWriter(new MemoryStream()), options)); + bool gotException = false; + try + { + Utf8JsonReader reader = default; + jsonModel.Deserialize(ref reader, options); + } + catch (FormatException) + { + gotException = true; + } + finally + { + Assert.IsTrue(gotException); + } + + gotException = false; + try + { + Utf8JsonReader reader = default; + ((IModelJsonSerializable)jsonModel).Deserialize(ref reader, options); + } + catch (FormatException) + { + gotException = true; + } + finally + { + Assert.IsTrue(gotException); + } + } + } + + [Test] + public void ThrowsIfWireIsNotJson() + { + if (ModelInstance is IModelJsonSerializable jsonModel && IsXmlWireFormat) + { + Assert.Throws(() => 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() + { + if (typeof(T).IsClass) + { + object model = null; + RequestContent content = ToRequestContent((T)model); + Assert.IsNull(content); + } + else + { + T model = default; + RequestContent content = ToRequestContent(model); + Assert.IsNotNull(content); + } + + Response response = null; + Assert.Throws(() => FromResponse(response)); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXDeserializationProxyTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXDeserializationProxyTests.cs new file mode 100644 index 000000000000..78abf3723fef --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXDeserializationProxyTests.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXDeserializationProxyTests + { + [TestCase("J")] + [TestCase("W")] + public void CanDeserializeModelX(string format) + { + ModelSerializerOptions options = new ModelSerializerOptions(format); + BinaryData data = new BinaryData(Encoding.UTF8.GetBytes("{\"kind\":\"X\",\"name\":\"xmodel\",\"xProperty\":100,\"extra\":\"stuff\"}")); + object modelX = ModelSerializer.Deserialize(data, typeof(ModelXDeserializationProxy), options); + Assert.IsNotNull(modelX); + Assert.IsInstanceOf(modelX); + Assert.AreEqual("X", ((ModelX)modelX).Kind); + Assert.AreEqual("xmodel", ((ModelX)modelX).Name); + Assert.AreEqual(100, ((ModelX)modelX).XProperty); + if (format == ModelSerializerFormat.Json) + { + var rawData = ModelTests.GetRawData((ModelX)modelX); + Assert.IsNotNull(rawData); + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXTests.cs new file mode 100644 index 000000000000..368479c4c3a2 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXTests.cs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXTests : ModelJsonTests + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ModelX/ModelXWireFormat.json")).TrimEnd(); + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelX)response; + + protected override void CompareModels(ModelX model, ModelX model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Name, model2.Name); + Assert.AreEqual(model.Kind, model2.Kind); + + Assert.AreEqual(model.Fields, model2.Fields); + Assert.AreEqual(model.KeyValuePairs, model2.KeyValuePairs); + Assert.AreEqual(model.NullProperty, model2.NullProperty); + + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(model.XProperty, model2.XProperty); + var rawData = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData); + Assert.IsNotNull(rawData2); + Assert.AreEqual(rawData.Count, rawData2.Count); + Assert.AreEqual(rawData["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"kind\":\"X\",\"name\":\"xmodel\""; + expected += ",\"fields\":[\"testField\"]"; + expected += ",\"keyValuePairs\":{\"color\":\"red\"}"; + if (format == ModelSerializerFormat.Json) + expected += ",\"xProperty\":100"; + if (format == ModelSerializerFormat.Json) + expected += ",\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(ModelX model, ModelSerializerFormat format) + { + Assert.AreEqual("X", model.Kind); + Assert.AreEqual("xmodel", model.Name); + + Assert.AreEqual(1, model.Fields.Count); + Assert.AreEqual("testField", model.Fields[0]); + Assert.AreEqual(1, model.KeyValuePairs.Count); + Assert.AreEqual("red", model.KeyValuePairs["color"]); + Assert.IsNull(model.NullProperty); + + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(100, model.XProperty); + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlCrossLibraryTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlCrossLibraryTests.cs new file mode 100644 index 000000000000..ce5d94676c97 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlCrossLibraryTests.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Xml; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.Public.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXmlCrossLibraryTests : ModelJsonTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ModelXmlX.xml")).TrimEnd(); + + protected override string JsonPayload => "{\"key\":\"Color\",\"value\":\"Red\",\"readOnlyProperty\":\"ReadOnly\",\"childTag\":{\"childValue\":\"ChildRed\",\"childReadOnlyProperty\":\"ChildReadOnly\"}}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelXmlCrossLibrary)response; + + [Test] + public void ThrowsIfMismatch() + { + ModelSerializerOptions jsonOptions = new ModelSerializerOptions(ModelSerializerFormat.Json); + ModelXmlCrossLibrary model = ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), jsonOptions); + + Assert.Throws(Is.InstanceOf(), () => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(WirePayload)), jsonOptions)); + + ModelSerializerOptions wireOptions = ModelSerializerOptions.DefaultWireOptions; + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), wireOptions)); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += "ChildRed"; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += "ChildReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + if (format == ModelSerializerFormat.Json) + { + var expectedSerializedString = "{\"key\":\"Color\",\"value\":\"Red\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"readOnlyProperty\":\"ReadOnly\""; + expectedSerializedString += ",\"childTag\":{\"childValue\":\"ChildRed\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"childReadOnlyProperty\":\"ChildReadOnly\""; + expectedSerializedString += "}}"; + return expectedSerializedString; + } + throw new InvalidOperationException($"Unknown format used in test {format}"); + } + + protected override void VerifyModel(ModelXmlCrossLibrary model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + Assert.IsNotNull(model.ChildModelXml); + Assert.AreEqual("ChildRed", model.ChildModelXml.ChildValue); + Assert.AreEqual("ChildReadOnly", model.ChildModelXml.ChildReadOnlyProperty); + } + + protected override void CompareModels(ModelXmlCrossLibrary model, ModelXmlCrossLibrary model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.ChildModelXml.ChildValue, model2.ChildModelXml.ChildValue); + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Data)) + // Assert.AreEqual(model.RenamedChildModelXml.ChildReadOnlyProperty, model2.RenamedChildModelXml.ChildReadOnlyProperty); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlOnlyTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlOnlyTests.cs new file mode 100644 index 000000000000..257b73244a1d --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlOnlyTests.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.Public.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXmlOnlyTests : ModelTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ModelXml.xml")).TrimEnd(); + + protected override string JsonPayload => string.Empty; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelXmlOnly)response; + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += "ChildRed"; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += "ChildReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + + protected override void VerifyModel(ModelXmlOnly model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + Assert.IsNotNull(model.RenamedChildModelXml); + Assert.AreEqual("ChildRed", model.RenamedChildModelXml.ChildValue); + Assert.AreEqual("ChildReadOnly", model.RenamedChildModelXml.ChildReadOnlyProperty); + } + + protected override void CompareModels(ModelXmlOnly model, ModelXmlOnly model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.RenamedChildModelXml.ChildValue, model2.RenamedChildModelXml.ChildValue); + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // Assert.AreEqual(model.RenamedChildModelXml.ChildReadOnlyProperty, model2.RenamedChildModelXml.ChildReadOnlyProperty); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlTests.cs new file mode 100644 index 000000000000..2f7259555061 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlTests.cs @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Xml; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXmlTests : ModelJsonTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ModelXml.xml")).TrimEnd(); + + protected override string JsonPayload => "{\"key\":\"Color\",\"value\":\"Red\",\"readOnlyProperty\":\"ReadOnly\",\"renamedChildModelXml\":{\"childValue\":\"ChildRed\",\"childReadOnlyProperty\":\"ChildReadOnly\"}}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelXml)response; + + [Test] + public void ThrowsIfMismatch() + { + ModelSerializerOptions jsonOptions = new ModelSerializerOptions(ModelSerializerFormat.Json); + ModelXml model = ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), jsonOptions); + + Assert.Throws(Is.InstanceOf(), () => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(WirePayload)), jsonOptions)); + + ModelSerializerOptions wireOptions = ModelSerializerOptions.DefaultWireOptions; + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), wireOptions)); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += "ChildRed"; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += "ChildReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + if (format == ModelSerializerFormat.Json) + { + var expectedSerializedString = "{\"key\":\"Color\",\"value\":\"Red\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"readOnlyProperty\":\"ReadOnly\""; + expectedSerializedString += ",\"renamedChildModelXml\":{\"childValue\":\"ChildRed\""; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += ",\"childReadOnlyProperty\":\"ChildReadOnly\""; + expectedSerializedString += "}}"; + return expectedSerializedString; + } + throw new InvalidOperationException($"Unknown format used in test {format}"); + } + + protected override void VerifyModel(ModelXml model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + Assert.IsNotNull(model.RenamedChildModelXml); + Assert.AreEqual("ChildRed", model.RenamedChildModelXml.ChildValue); + Assert.AreEqual("ChildReadOnly", model.RenamedChildModelXml.ChildReadOnlyProperty); + } + + protected override void CompareModels(ModelXml model, ModelXml model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.RenamedChildModelXml.ChildValue, model2.RenamedChildModelXml.ChildValue); + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // Assert.AreEqual(model.RenamedChildModelXml.ChildReadOnlyProperty, model2.RenamedChildModelXml.ChildReadOnlyProperty); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Animal.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Animal.cs new file mode 100644 index 000000000000..b6d43ba572e9 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Animal.cs @@ -0,0 +1,147 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class Animal : IUtf8JsonSerializable, IModelJsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public bool IsHungry { get; set; } = false; + public double Weight { get; set; } = 1.1d; + public string LatinName { get; private set; } = "Animalia"; + public string Name { get; set; } = "Animal"; + + public Animal() + { + } + + public Animal(double weight, string latinName, string name, bool isHungry) + { + Weight = weight; + LatinName = latinName; + Name = name; + IsHungry = isHungry; + } + + internal Animal(double weight, string latinName, string name, bool isHungry, Dictionary rawData) + { + Weight = weight; + LatinName = latinName; + Name = name; + IsHungry = isHungry; + RawData = rawData; + } + + internal Animal(string name) + { + Name = name; + } + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("latinName"u8); + writer.WriteStringValue(LatinName); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("isHungry"u8); + writer.WriteBooleanValue(IsHungry); + writer.WritePropertyName("weight"u8); + writer.WriteNumberValue(Weight); + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static Animal DeserializeAnimal(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + double weight = default; + string name = ""; + string latinName = ""; + bool isHungry = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("weight"u8)) + { + weight = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("latinName"u8)) + { + latinName = property.Value.GetString(); + continue; + } + if (property.NameEquals("isHungry"u8)) + { + isHungry = property.Value.GetBoolean(); + continue; + } + + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new Animal(weight, latinName, name, isHungry, rawData); + } + #endregion + + #region InterfaceImplementation + + Animal IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeAnimal(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + Animal IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeAnimal(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + #endregion + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/CatReadOnlyProperty.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/CatReadOnlyProperty.cs new file mode 100644 index 000000000000..0996ac733a73 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/CatReadOnlyProperty.cs @@ -0,0 +1,138 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class CatReadOnlyProperty : Animal, IModelJsonSerializable, IUtf8JsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public CatReadOnlyProperty(double weight, string latinName, string name, bool isHungry, bool hasWhiskers) : base(weight, "Felis catus", name, isHungry) + { + HasWhiskers = hasWhiskers; + } + + internal CatReadOnlyProperty(double weight, string latinName, string name, bool isHungry, bool hasWhiskers, Dictionary rawData) : this(weight, latinName, name, isHungry, hasWhiskers) + { + RawData = rawData; + } + + internal CatReadOnlyProperty() + { + } + + public bool HasWhiskers { get; private set; } = true; + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("latinName"u8); + writer.WriteStringValue(LatinName); + + writer.WritePropertyName("hasWhiskers"u8); + writer.WriteBooleanValue(HasWhiskers); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("isHungry"u8); + writer.WriteBooleanValue(IsHungry); + writer.WritePropertyName("weight"u8); + writer.WriteNumberValue(Weight); + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static CatReadOnlyProperty DeserializeCatReadOnlyProperty(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + double weight = default; + string name = ""; + string latinName = ""; + bool isHungry = default; + bool hasWhiskers = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("weight"u8)) + { + weight = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("latinName"u8)) + { + latinName = property.Value.GetString(); + continue; + } + + if (property.NameEquals("isHungry"u8)) + { + isHungry = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("hasWhiskers"u8)) + { + hasWhiskers = property.Value.GetBoolean(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means its an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new CatReadOnlyProperty(weight, latinName, name, isHungry, hasWhiskers, rawData); + } + + CatReadOnlyProperty IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeCatReadOnlyProperty(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + CatReadOnlyProperty IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeCatReadOnlyProperty(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + #endregion + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ChildModelXmlOnly.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ChildModelXmlOnly.cs new file mode 100644 index 000000000000..703eb6f1f02f --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ChildModelXmlOnly.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("ChildTag")] + public class ChildModelXmlOnly : IXmlSerializable, IModelSerializable + { + internal ChildModelXmlOnly() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// is null. + public ChildModelXmlOnly(string value, string readonlyProperty) + { + Argument.AssertNotNull(value, nameof(value)); + + ChildValue = value; + ChildReadOnlyProperty = readonlyProperty; + } + + /// Gets or sets the value. + [XmlElement("ChildValue")] + public string ChildValue { get; set; } + /// Gets or sets the value. + [XmlElement("ChildReadOnlyProperty")] + public string ChildReadOnlyProperty { get; } + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + if (options.Format != ModelSerializerFormat.Wire) + throw new NotSupportedException($"{nameof(ChildModelXmlOnly)} does not support '{options.Format}' format"); + + writer.WriteStartElement(nameHint ?? "ChildTag"); + writer.WriteStartElement("ChildValue"); + writer.WriteValue(ChildValue); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ChildReadOnlyProperty"); + writer.WriteValue(ChildReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + internal static ChildModelXmlOnly DeserializeChildModelXmlOnly(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (options.Format != ModelSerializerFormat.Wire) + throw new NotSupportedException($"{nameof(ChildModelXmlOnly)} does not support '{options.Format}' format"); + + string value = default; + string readonlyProperty = default; + if (element.Element("ChildValue") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ChildReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + return new ChildModelXmlOnly(value, readonlyProperty); + } + + ChildModelXmlOnly IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + => DeserializeChildModelXmlOnly(XElement.Load(data.ToStream()), options); + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListProperty.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListProperty.cs new file mode 100644 index 000000000000..31448ddc11c5 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListProperty.cs @@ -0,0 +1,186 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + [JsonConverter(typeof(DogListPropertyConverter))] + public class DogListProperty : Animal, IModelJsonSerializable, IUtf8JsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + public IList FoodConsumed { get; private set; } + + public DogListProperty(string name) : base(name) + { + Name = name; + FoodConsumed = new ChangeTrackingList(); + } + + internal DogListProperty(double weight, string latinName, string name, bool isHungry, IList foodConsumed, Dictionary rawData) : base(weight, latinName, name, isHungry, rawData) + { + RawData = rawData; + FoodConsumed = foodConsumed; + } + + public DogListProperty() + { + FoodConsumed = new ChangeTrackingList(); + } + + public static explicit operator DogListProperty(Response response) + { + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeDogListProperty(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + public static implicit operator RequestContent(DogListProperty dog) + { + return RequestContent.Create(dog, ModelSerializerOptions.DefaultWireOptions); + } + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("latinName"u8); + writer.WriteStringValue(LatinName); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("isHungry"u8); + writer.WriteBooleanValue(IsHungry); + writer.WritePropertyName("weight"u8); + writer.WriteNumberValue(Weight); + + if (Optional.IsCollectionDefined(FoodConsumed)) + { + writer.WritePropertyName("foodConsumed"u8); + writer.WriteStartArray(); + foreach (var item in FoodConsumed) + { + writer.WriteStringValue($"{item}"); + } + writer.WriteEndArray(); + } + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static DogListProperty DeserializeDogListProperty(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + double weight = default; + string name = ""; + string latinName = ""; + bool isHungry = default; + Dictionary rawData = new Dictionary(); + List foodConsumed = new List(); + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("weight"u8)) + { + weight = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("latinName"u8)) + { + latinName = property.Value.GetString(); + continue; + } + if (property.NameEquals("isHungry"u8)) + { + isHungry = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("foodConsumed"u8)) + { + foreach (var item in property.Value.EnumerateArray()) + { + foodConsumed.Add(item.GetString()); + } + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means its an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new DogListProperty(weight, latinName, name, isHungry, foodConsumed, rawData); + } + #endregion + + internal class DogListPropertyConverter : JsonConverter + { + public override DogListProperty Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var model = DeserializeDogListProperty(JsonDocument.ParseValue(ref reader).RootElement, GetOptions(options)); + //marker used for testing to know if this converter fires + model.RawData.Add("DogListPropertyConverterMarker", new BinaryData("true")); + return model; + } + + public override void Write(Utf8JsonWriter writer, DogListProperty value, JsonSerializerOptions options) + { + ((IModelJsonSerializable)value).Serialize(writer, GetOptions(options)); + } + + private ModelSerializerOptions GetOptions(JsonSerializerOptions options) + { + //pulls the additional properties setting from the ModelJsonConverter if it exists + //if it does not exist it uses the default value of true for azure sdk use cases + var modelConverter = options.Converters.FirstOrDefault(c => c.GetType() == typeof(ModelJsonConverter)) as ModelJsonConverter; + return modelConverter is not null ? modelConverter.ModelSerializerOptions : ModelSerializerOptions.DefaultWireOptions; + } + } + DogListProperty IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeDogListProperty(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + DogListProperty IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeDogListProperty(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListPropertyBlankConverter.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListPropertyBlankConverter.cs new file mode 100644 index 000000000000..188048b7250d --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListPropertyBlankConverter.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class DogListPropertyBlankConverter : JsonConverter + { + public override DogListProperty Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var model = JsonDocument.ParseValue(ref reader); + return new DogListProperty(); + } + + public override void Write(Utf8JsonWriter writer, DogListProperty value, JsonSerializerOptions options) + { + return; + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Envelope.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Envelope.cs new file mode 100644 index 000000000000..3d828ce22275 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Envelope.cs @@ -0,0 +1,183 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class Envelope : IModelJsonSerializable>, IUtf8JsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public string ReadOnlyProperty { get; private set; } = "readonly"; + + public Envelope() + { + } + + public Envelope(string readOnlyProperty) + { + ReadOnlyProperty = readOnlyProperty; + } + + internal Envelope(string readOnlyProperty, CatReadOnlyProperty modelA, T modelT, Dictionary rawData) + { + ReadOnlyProperty = readOnlyProperty; + ModelA = modelA; + ModelT = modelT; + RawData = rawData; + } + + public CatReadOnlyProperty ModelA { get; set; } + public T ModelT { get; set; } + + public static implicit operator RequestContent(Envelope envelope) + { + if (envelope == null) + { + return null; + } + + return RequestContent.Create(envelope, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator Envelope(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeEnvelope(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable>)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable>.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + + writer.WritePropertyName("modelA"u8); + ((IModelJsonSerializable)ModelA).Serialize(writer, options); + writer.WritePropertyName("modelC"u8); + SerializeT(writer, options); + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static Envelope DeserializeEnvelope(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string readonlyProperty = ""; + CatReadOnlyProperty modelA = new CatReadOnlyProperty(); + T modelT = default(T); + Dictionary rawData = new Dictionary(); + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("readOnlyProperty"u8)) + { + readonlyProperty = property.Value.GetString(); + continue; + } + if (property.NameEquals("modelA"u8)) + { + modelA = CatReadOnlyProperty.DeserializeCatReadOnlyProperty(property.Value, options); + continue; + } + if (property.NameEquals("modelC"u8)) + { + modelT = DeserializeT(property.Value, options); + continue; + } + + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an modelC property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new Envelope(readonlyProperty, modelA, modelT, rawData); + } + + private void SerializeT(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ObjectSerializer serializer = GetObjectSerializer(options); + BinaryData data = serializer.Serialize(ModelT); +#if NET6_0_OR_GREATER + writer.WriteRawValue(data); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(data.ToString()).RootElement); +#endif + } + + private static ObjectSerializer GetObjectSerializer(ModelSerializerOptions options) + { + var serializer = options.ObjectSerializerResolver is not null ? options.ObjectSerializerResolver(typeof(T)) : null; + return serializer ?? JsonObjectSerializer.Default; + } + + private static T DeserializeT(JsonElement element, ModelSerializerOptions options) + { + ObjectSerializer serializer = GetObjectSerializer(options); + MemoryStream m = new MemoryStream(); + Utf8JsonWriter w = new Utf8JsonWriter(m); + element.WriteTo(w); + w.Flush(); + m.Position = 0; + return (T)serializer.Deserialize(m, typeof(T), default); + } + + Envelope IModelSerializable>.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeEnvelope(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + Envelope IModelJsonSerializable>.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeEnvelope(doc.RootElement, options); + } + + BinaryData IModelSerializable>.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + #endregion + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/JsonModelForCombinedInterface.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/JsonModelForCombinedInterface.cs new file mode 100644 index 000000000000..e2d6c9317bd8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/JsonModelForCombinedInterface.cs @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + internal class JsonModelForCombinedInterface : IUtf8JsonSerializable, IModelJsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public JsonModelForCombinedInterface() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public JsonModelForCombinedInterface(string key, string value, string readOnlyProperty) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readOnlyProperty; + } + + internal JsonModelForCombinedInterface(string key, string value, string readOnlyProperty, Dictionary rawData) + { + Key = key; + Value = value; + ReadOnlyProperty = readOnlyProperty; + RawData = rawData; + } + + /// Gets or sets the key. + public string Key { get; set; } + /// Gets or sets the value. + public string Value { get; set; } + public string ReadOnlyProperty { get; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static JsonModelForCombinedInterface DeserializeJsonModelForCombinedInterface(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + Dictionary rawData = new Dictionary(); + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means its an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new JsonModelForCombinedInterface(key, value, readOnlyProperty, rawData); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + JsonModelForCombinedInterface IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeJsonModelForCombinedInterface(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + JsonModelForCombinedInterface IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeJsonModelForCombinedInterface(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlCrossLibrary.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlCrossLibrary.cs new file mode 100644 index 000000000000..4b13e96b1e4c --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlCrossLibrary.cs @@ -0,0 +1,240 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + public class ModelXmlCrossLibrary : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + internal ModelXmlCrossLibrary() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public ModelXmlCrossLibrary(string key, string value, string readonlyProperty, ChildModelXml childModelXml) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readonlyProperty; + ChildModelXml = childModelXml; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + [XmlElement("ChildTag")] + public ChildModelXml ChildModelXml { get; set; } + + public static implicit operator RequestContent(ModelXmlCrossLibrary modelXmlCrossLibrary) + { + if (modelXmlCrossLibrary == null) + { + return null; + } + + return RequestContent.Create((IModelSerializable)modelXmlCrossLibrary, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelXmlCrossLibrary(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeModelXmlCrossLibrary(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + public void Serialize(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + var childModelXml = ModelSerializer.Serialize(ChildModelXml, options); + var bytes = childModelXml.ToArray(); + int start = bytes.AsSpan(1).IndexOf((byte)'>') + 2; + var chars = Encoding.UTF8.GetChars(bytes, start, bytes.Length - start); + writer.WriteRaw(chars, 0, chars.Length); + writer.WriteEndElement(); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + writer.WritePropertyName("childTag"u8); + ((IModelJsonSerializable)ChildModelXml).Serialize(writer, options); + writer.WriteEndObject(); + } + + public static ModelXmlCrossLibrary DeserializeModelXmlCrossLibrary(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readonlyProperty = default; + ChildModelXml childModelXml = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + if (element.Element("ChildTag") is XElement renamedChildModelXmlElement) + { + using MemoryStream stream = new MemoryStream(); + renamedChildModelXmlElement.Save(stream); + BinaryData data = stream.Position > int.MaxValue + ? BinaryData.FromStream(stream) + : new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + childModelXml = ModelSerializer.Deserialize(data, options); + } + return new ModelXmlCrossLibrary(key, value, readonlyProperty, childModelXml); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + internal static ModelXmlCrossLibrary DeserializeModelXmlCrossLibrary(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + ChildModelXml childModelXml = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + if (property.NameEquals("childTag"u8)) + { + childModelXml = ModelSerializer.Deserialize(BinaryData.FromString(property.Value.GetRawText()), options);// ChildModelXml.DeserializeChildModelXml(property.Value, options); + continue; + } + } + return new ModelXmlCrossLibrary(key, value, readOnlyProperty, childModelXml); + } + + ModelXmlCrossLibrary IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeModelXmlCrossLibrary(doc.RootElement, options); + } + else + { + return DeserializeModelXmlCrossLibrary(XElement.Load(data.ToStream()), options); + } + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + Serialize(writer, options); + } + + ModelXmlCrossLibrary IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelXmlCrossLibrary(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlOnly.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlOnly.cs new file mode 100644 index 000000000000..5c8f81f96489 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlOnly.cs @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + public class ModelXmlOnly : IXmlSerializable, IModelSerializable + { + internal ModelXmlOnly() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public ModelXmlOnly(string key, string value, string readonlyProperty, ChildModelXmlOnly childModel) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readonlyProperty; + RenamedChildModelXml = childModel; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + [XmlElement("RenamedChildModelXml")] + public ChildModelXmlOnly RenamedChildModelXml { get; set; } + + public static implicit operator RequestContent(ModelXmlOnly modelXml) + { + if (modelXml == null) + { + return null; + } + + return RequestContent.Create(modelXml, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelXmlOnly(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeModelXmlOnly(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + public void Serialize(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteObjectValue(RenamedChildModelXml, "RenamedChildModelXml"); + writer.WriteEndElement(); + } + + public static ModelXmlOnly DeserializeModelXmlOnly(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readonlyProperty = default; + ChildModelXmlOnly childModelXml = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + if (element.Element("RenamedChildModelXml") is XElement renamedChildModelXmlElement) + { + childModelXml = ChildModelXmlOnly.DeserializeChildModelXmlOnly(renamedChildModelXmlElement, options); + } + return new ModelXmlOnly(key, value, readonlyProperty, childModelXml); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + ModelXmlOnly IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeModelXmlOnly(XElement.Load(data.ToStream()), options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/XmlModelForCombinedInterface.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/XmlModelForCombinedInterface.cs new file mode 100644 index 000000000000..b8d35812b851 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/XmlModelForCombinedInterface.cs @@ -0,0 +1,214 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + internal class XmlModelForCombinedInterface : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + public XmlModelForCombinedInterface() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public XmlModelForCombinedInterface(string key, string value, string readOnlyProperty) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readOnlyProperty; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + + public static implicit operator RequestContent(XmlModelForCombinedInterface xmlModelForCombinedInterface) + { + if (xmlModelForCombinedInterface == null) + { + return null; + } + + return RequestContent.Create((IModelSerializable)xmlModelForCombinedInterface, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator XmlModelForCombinedInterface(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeXmlModelForCombinedInterface(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + internal static XmlModelForCombinedInterface DeserializeXmlModelForCombinedInterface(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readOnlyPropertyElement) + { + readOnlyProperty = (string)readOnlyPropertyElement; + } + return new XmlModelForCombinedInterface(key, value, readOnlyProperty); + } + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + writer.WriteEndObject(); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + internal static XmlModelForCombinedInterface DeserializeXmlModelForCombinedInterface(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + } + return new XmlModelForCombinedInterface(key, value, readOnlyProperty); + } + + XmlModelForCombinedInterface IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeXmlModelForCombinedInterface(doc.RootElement, options); + } + else + { + return DeserializeXmlModelForCombinedInterface(XElement.Load(data.ToStream()), options); + } + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + + Serialize(writer, options); + } + + XmlModelForCombinedInterface IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeXmlModelForCombinedInterface(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ResourceProviderDataTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ResourceProviderDataTests.cs new file mode 100644 index 000000000000..9740b86da459 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ResourceProviderDataTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ResourceManager.Resources; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ResourceProviderDataTests : ModelJsonTests + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ResourceProviderData/ResourceProviderData-Collapsed.json")).TrimEnd(); + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ResourceProviderData)response; + + protected override void CompareModels(ResourceProviderData model, ResourceProviderData model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Id, model2.Id); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) => WirePayload; + + protected override void VerifyModel(ResourceProviderData model, ModelSerializerFormat format) + { + Assert.IsNotNull(model); + Assert.IsNotNull(model.Id); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/RoundTripStrategy.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/RoundTripStrategy.cs new file mode 100644 index 000000000000..efc2cb3f4ab5 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/RoundTripStrategy.cs @@ -0,0 +1,262 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection.Metadata.Ecma335; +using System.Text; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.TestFramework; + +#pragma warning disable SA1402 // File may only contain a single type +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public abstract class RoundTripStrategy + { + public abstract object Deserialize(string payload, object model, ModelSerializerOptions options); + public abstract BinaryData Serialize(T model, ModelSerializerOptions options); + public abstract bool IsExplicitJsonSerialize { get; } + public abstract bool IsExplicitJsonDeserialize { get; } + } + + public class ModelSerializerStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.Serialize(model, options); + } + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class ModelSerializerFormatOverloadStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.Serialize(model, options.Format); + } + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options.Format); + } + } + + public class ModelSerializerNonGenericStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.Serialize((object)model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), typeof(T), options); + } + } + + public class ModelInterfaceStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return model.Serialize(options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class ModelInterfaceNonGenericStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ((IModelSerializable)model).Serialize(options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonInterfaceStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + using MemoryStream stream = new MemoryStream(); + using Utf8JsonWriter writer = new Utf8JsonWriter(stream); + model.Serialize(writer, options); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelJsonSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonModelWriterStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.SerializeCore(model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelJsonSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonInterfaceNonGenericStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.SerializeCore((IModelJsonSerializable)model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelJsonSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonInterfaceUtf8ReaderStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => true; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + using MemoryStream stream = new MemoryStream(); + using Utf8JsonWriter writer = new Utf8JsonWriter(stream); + model.Serialize(writer, options); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + var reader = new Utf8JsonReader(new BinaryData(Encoding.UTF8.GetBytes(payload))); + return ((IModelJsonSerializable)model).Deserialize(ref reader, options); + } + } + + public class JsonInterfaceUtf8ReaderNonGenericStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => true; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.SerializeCore((IModelJsonSerializable)model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + var reader = new Utf8JsonReader(new BinaryData(Encoding.UTF8.GetBytes(payload))); + return ((IModelJsonSerializable)model).Deserialize(ref reader, options); + } + } + + public class CastStrategy : RoundTripStrategy where T : IModelSerializable + { + private Func _toRequestContent; + private Func _fromResponse; + + public CastStrategy(Func toRequestContent, Func fromResponse) + { + _toRequestContent = toRequestContent; + _fromResponse = fromResponse; + } + + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + RequestContent content = _toRequestContent(model); + content.TryComputeLength(out var length); + using var stream = new MemoryStream((int)length); + content.WriteTo(stream, default); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + var response = new MockResponse(200); + response.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(payload)); + return _fromResponse(response); + } + } + + public class ModelJsonConverterStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => true; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new ModelJsonConverter(options)); + return BinaryData.FromString(JsonSerializer.Serialize(model, jsonSerializerOptions)); + } + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new ModelJsonConverter(options)); + return JsonSerializer.Deserialize(payload, jsonSerializerOptions); + } + } +} +#pragma warning restore SA1402 // File may only contain a single type diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UnknownBaseModelTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UnknownBaseModelTests.cs new file mode 100644 index 000000000000..d81a640721a0 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UnknownBaseModelTests.cs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Linq; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class UnknownBaseModelTests : ModelJsonTests + { + protected override BaseModel GetModelInstance() + { + var typeToActivate = typeof(BaseModel).Assembly.GetTypes().FirstOrDefault(t => t.Name == $"Unknown{typeof(BaseModel).Name}"); + return Activator.CreateInstance(typeToActivate, true) as BaseModel; + } + + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"kind\":\"Z\",\"name\":\"zmodel\",\"zProperty\":1.5,\"extra\":\"stuff\"}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (BaseModel)response; + + protected override void CompareModels(BaseModel model, BaseModel model2, ModelSerializerFormat format) + { + Assert.AreEqual("UnknownBaseModel", model.GetType().Name); + Assert.AreEqual("UnknownBaseModel", model2.GetType().Name); + Assert.AreEqual(model.Kind, model2.Kind); + Assert.AreEqual(model.Name, model2.Name); + var rawData = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData); + Assert.IsNotNull(rawData2); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(rawData.Count, rawData2.Count); + Assert.AreEqual(rawData["zProperty"].ToObjectFromJson(), rawData2["zProperty"].ToObjectFromJson()); + Assert.AreEqual(rawData["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"kind\":\"Z\",\"name\":\"zmodel\""; + if (format == ModelSerializerFormat.Json) + expected += ",\"zProperty\":1.5,\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(BaseModel model, ModelSerializerFormat format) + { + Assert.AreEqual("UnknownBaseModel", model.GetType().Name); + Assert.AreEqual("Z", model.Kind); + Assert.AreEqual("zmodel", model.Name); + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(1.5, rawData["zProperty"].ToObjectFromJson()); + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UsingJsonSerializerTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UsingJsonSerializerTests.cs new file mode 100644 index 000000000000..4d1a05616025 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UsingJsonSerializerTests.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class UsingJsonSerializerTests + { + [TestCase("J")] + [TestCase("W")] + public void CanSerializeTwoModelsWithSameConverter(string format) + { + string modelYResponse = "{\"kind\":\"Y\",\"name\":\"ymodel\",\"yProperty\":\"100\",\"extra\":\"stuff\"}"; + string modelXResponse = "{\"kind\":\"X\",\"name\":\"xmodel\",\"xProperty\":100,\"extra\":\"stuff\"}"; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new ModelJsonConverter(format)); + ModelY modelY = JsonSerializer.Deserialize(modelYResponse, options); + + Assert.AreEqual("Y", modelY.Kind); + Assert.AreEqual("ymodel", modelY.Name); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("100", modelY.YProperty); + + var additionalProperties = ModelTests.GetRawData(modelY); + Assert.IsNotNull(additionalProperties); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("stuff", additionalProperties["extra"].ToObjectFromJson()); + + string expectedModelY = "{"; + expectedModelY += "\"kind\":\"Y\",\"name\":\"ymodel\""; + if (format == ModelSerializerFormat.Json) + expectedModelY += ",\"yProperty\":\"100\",\"extra\":\"stuff\""; + expectedModelY += "}"; + + var actualModelY = JsonSerializer.Serialize(modelY, options); + Assert.AreEqual(expectedModelY, actualModelY); + + ModelX modelX = JsonSerializer.Deserialize(modelXResponse, options); + + Assert.AreEqual("X", modelX.Kind); + Assert.AreEqual("xmodel", modelX.Name); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual(100, modelX.XProperty); + + additionalProperties = ModelTests.GetRawData(modelX); + Assert.IsNotNull(additionalProperties); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("stuff", additionalProperties["extra"].ToObjectFromJson()); + + string expectedModelX = "{"; + expectedModelX += "\"kind\":\"X\""; + expectedModelX += ",\"name\":\"xmodel\""; + if (format == ModelSerializerFormat.Json) + expectedModelX += ",\"xProperty\":100"; + if (format == ModelSerializerFormat.Json) + expectedModelX += ",\"extra\":\"stuff\""; + expectedModelX += "}"; + + var actualModelX = JsonSerializer.Serialize(modelX, options); + Assert.AreEqual(expectedModelX, actualModelX); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/VerifyModels.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/VerifyModels.cs new file mode 100644 index 000000000000..3c8aea67019e --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/VerifyModels.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Azure.Core.Serialization; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class VerifyModels + { + public static void CheckAnimals(Animal x, Animal y, ModelSerializerOptions options) + { + VerifyProperties(x, y, options); + } + + private static void VerifyProperties(Animal x, Animal y, ModelSerializerOptions options) + { + if (options.Format == ModelSerializerFormat.Json) + Assert.That(x.LatinName, Is.EqualTo(y.LatinName)); + Assert.That(x.Name, Is.EqualTo(y.Name)); + Assert.That(x.Weight, Is.EqualTo(y.Weight)); + + if (options.Format == ModelSerializerFormat.Json) + { + var additionalPropertiesX = typeof(Animal).GetProperty("RawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(x) as Dictionary; + var additionalPropertiesY = typeof(Animal).GetProperty("RawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(y) as Dictionary; + + Assert.AreEqual(additionalPropertiesX.Count, additionalPropertiesY.Count); + + foreach (var additionalProperty in additionalPropertiesX) + { + Assert.IsTrue(additionalPropertiesY.ContainsKey(additionalProperty.Key)); + Assert.AreEqual(additionalProperty.Value.ToString(), additionalPropertiesY[additionalProperty.Key].ToString()); + } + foreach (var additionalProperty in additionalPropertiesY) + { + Assert.IsTrue(additionalPropertiesX.ContainsKey(additionalProperty.Key)); + Assert.AreEqual(additionalProperty.Value.ToString(), additionalPropertiesX[additionalProperty.Key].ToString()); + } + } + } + + public static void CheckCats(CatReadOnlyProperty x, CatReadOnlyProperty y, ModelSerializerOptions options) + { + VerifyProperties(x, y, options); + Assert.That(x.HasWhiskers, Is.EqualTo(y.HasWhiskers)); + } + + public static void CheckDogs(DogListProperty x, DogListProperty y, ModelSerializerOptions options) + { + VerifyProperties(x, y, options); + Assert.That(x.FoodConsumed, Is.EqualTo(y.FoodConsumed)); + } + + public static string NormalizeNewLines(string value) + { + return value + .Replace("\r\n", "\n") + .Replace("\n", Environment.NewLine); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/XmlModelForCombinedInterfaceTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/XmlModelForCombinedInterfaceTests.cs new file mode 100644 index 000000000000..0543b09a435b --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/XmlModelForCombinedInterfaceTests.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Azure.Core.Serialization; +using Azure.Core.Tests.Public.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class XmlModelForCombinedInterfaceTests : ModelJsonTests + { + protected override string JsonPayload => "{\"key\":\"Color\",\"value\":\"Red\",\"readOnlyProperty\":\"ReadOnly\"}"; + + protected override string WirePayload => "" + + "Color" + + "Red" + + "ReadOnly" + + ""; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (XmlModelForCombinedInterface)response; + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + if (format == ModelSerializerFormat.Json) + { + var expectedSerializedString = "{\"key\":\"Color\",\"value\":\"Red\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"readOnlyProperty\":\"ReadOnly\""; + expectedSerializedString += "}"; + return expectedSerializedString; + } + throw new InvalidOperationException($"Unknown format used in test {format}"); + } + + protected override void VerifyModel(XmlModelForCombinedInterface model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + } + + protected override void CompareModels(XmlModelForCombinedInterface model, XmlModelForCombinedInterface model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + } + } +}