зеркало из https://github.com/Azure/autorest.git
Ruby - Move serialization/deserialization into clientruntime from sdk (#1106)
This commit is contained in:
Родитель
b4a493df69
Коммит
6b71ddaf37
|
@ -56,6 +56,9 @@ ipch/
|
|||
*.psess
|
||||
*.vsp
|
||||
|
||||
# VS Code settings
|
||||
*.vscode
|
||||
|
||||
# Code analysis
|
||||
*.CodeAnalysisLog.xml
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace Microsoft.Rest.Generator.Azure.Ruby
|
|||
{
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
string serializationLogic = type.DeserializeType(this.Scope, variableName);
|
||||
string serializationLogic = GetDeserializationString(type, variableName, variableName);
|
||||
return builder.AppendLine(serializationLogic).ToString();
|
||||
}
|
||||
|
||||
|
@ -119,9 +119,9 @@ namespace Microsoft.Rest.Generator.Azure.Ruby
|
|||
get
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
"MsRestAzure"
|
||||
};
|
||||
{
|
||||
"MsRestAzure"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Rest.Generator.Azure.Ruby.Templates;
|
||||
using Microsoft.Rest.Generator.ClientModel;
|
||||
using Microsoft.Rest.Generator.Ruby;
|
||||
using Microsoft.Rest.Generator.Utilities;
|
||||
using Microsoft.Rest.Generator.Azure.Ruby.Templates;
|
||||
|
||||
namespace Microsoft.Rest.Generator.Azure.Ruby
|
||||
{
|
||||
|
@ -45,36 +45,6 @@ namespace Microsoft.Rest.Generator.Azure.Ruby
|
|||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates code for model serialization.
|
||||
/// </summary>
|
||||
/// <param name="variableName">Variable serialize model from.</param>
|
||||
/// <param name="type">The type of the model.</param>
|
||||
/// <returns>The code for serialization in string format.</returns>
|
||||
public override string SerializeProperty(string variableName, IType type)
|
||||
{
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
string serializationLogic = type.AzureSerializeType(this.Scope, variableName);
|
||||
builder.AppendLine(serializationLogic);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates code for model deserialization.
|
||||
/// </summary>
|
||||
/// <param name="variableName">Variable deserialize model from.</param>
|
||||
/// <param name="type">The type of the model.</param>
|
||||
/// <returns>The code for вуserialization in string format.</returns>
|
||||
public override string DeserializeProperty(string variableName, IType type)
|
||||
{
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
string serializationLogic = type.AzureDeserializeType(this.Scope, variableName);
|
||||
return builder.AppendLine(serializationLogic).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of modules/classes which need to be included.
|
||||
|
|
|
@ -37,7 +37,10 @@ def @(Model.Name)(@(Model.MethodParameterDeclaration))
|
|||
promise = promise.then do |response|
|
||||
# Defining deserialization method.
|
||||
deserialize_method = lambda do |parsed_response|
|
||||
@(Model.DeserializePollingResponse("parsed_response", Model.ReturnType.Body))
|
||||
@if(Model.ReturnType.Body != null)
|
||||
{
|
||||
@:@(Model.DeserializePollingResponse("parsed_response", Model.ReturnType.Body))
|
||||
}
|
||||
end
|
||||
|
||||
@EmptyLine
|
||||
|
@ -79,7 +82,10 @@ def @(Model.Name)(@(Model.MethodParameterDeclaration))
|
|||
promise = promise.then do |response|
|
||||
# Defining deserialization method.
|
||||
deserialize_method = lambda do |parsed_response|
|
||||
@(Model.DeserializePollingResponse("parsed_response", Model.ReturnType.Body))
|
||||
@if(Model.ReturnType.Body != null)
|
||||
{
|
||||
@:@(Model.DeserializePollingResponse("parsed_response", Model.ReturnType.Body))
|
||||
}
|
||||
end
|
||||
|
||||
@EmptyLine
|
||||
|
|
|
@ -15,6 +15,8 @@ describe String do
|
|||
|
||||
client = AutoRestSwaggerBATService.new(@credentials, @base_url)
|
||||
@string_client = StringModule::String.new(client)
|
||||
|
||||
@enum_client = StringModule::Enum.new(client)
|
||||
end
|
||||
|
||||
it 'should create test service' do
|
||||
|
@ -62,4 +64,12 @@ describe String do
|
|||
expect(result.response.status).to eq(200)
|
||||
expect(result.body).to be_nil
|
||||
end
|
||||
it 'should support valid enum valid value' do
|
||||
result = @enum_client.get_not_expandable_async().value!
|
||||
expect(result.response.status).to eq(200)
|
||||
expect(result.response.body).to include('red color')
|
||||
end
|
||||
it 'should correctly handle invalid values for enum' do
|
||||
expect { @enum_client.put_not_expandable_async('orange color').value! }.to raise_error(MsRest::ValidationError)
|
||||
end
|
||||
end
|
|
@ -2,13 +2,15 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Rest.Generator.ClientModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.Rest.Generator.ClientModel;
|
||||
|
||||
namespace Microsoft.Rest.Generator.Ruby.TemplateModels
|
||||
{
|
||||
using Utilities;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Keeps a few aux method used across all templates/models.
|
||||
|
@ -262,224 +264,6 @@ namespace Microsoft.Rest.Generator.Ruby.TemplateModels
|
|||
return client.ModelTypes.Any(mt => mt.Extensions.Count == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates Ruby code in form of string for deserializing object of given type.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of object needs to be deserialized.</param>
|
||||
/// <param name="scope">Current scope.</param>
|
||||
/// <param name="valueReference">Reference to object which needs to be deserialized.</param>
|
||||
/// <returns>Generated Ruby code in form of string.</returns>
|
||||
public static string DeserializeType(
|
||||
this IType type,
|
||||
IScopeProvider scope,
|
||||
string valueReference)
|
||||
{
|
||||
var composite = type as CompositeType;
|
||||
var sequence = type as SequenceType;
|
||||
var dictionary = type as DictionaryType;
|
||||
var primary = type as PrimaryType;
|
||||
var enumType = type as EnumType;
|
||||
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
if (primary != null)
|
||||
{
|
||||
if (primary.Type == KnownPrimaryType.Int || primary.Type == KnownPrimaryType.Long)
|
||||
{
|
||||
return builder.AppendLine("{0} = Integer({0}) unless {0}.to_s.empty?", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.Double)
|
||||
{
|
||||
return builder.AppendLine("{0} = Float({0}) unless {0}.to_s.empty?", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.ByteArray)
|
||||
{
|
||||
return builder.AppendLine("{0} = Base64.strict_decode64({0}).unpack('C*') unless {0}.to_s.empty?", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.Date)
|
||||
{
|
||||
return builder.AppendLine("{0} = MsRest::Serialization.deserialize_date({0}) unless {0}.to_s.empty?", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.DateTime)
|
||||
{
|
||||
return builder.AppendLine("{0} = DateTime.parse({0}) unless {0}.to_s.empty?", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.DateTimeRfc1123)
|
||||
{
|
||||
return builder.AppendLine("{0} = DateTime.parse({0}) unless {0}.to_s.empty?", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.UnixTime)
|
||||
{
|
||||
return builder.AppendLine("{0} = DateTime.strptime({0}.to_s, '%s') unless {0}.to_s.empty?", valueReference).ToString();
|
||||
}
|
||||
}
|
||||
else if (enumType != null && !string.IsNullOrEmpty(enumType.Name))
|
||||
{
|
||||
return builder
|
||||
.AppendLine("if (!{0}.nil? && !{0}.empty?)", valueReference)
|
||||
.AppendLine(
|
||||
" enum_is_valid = {0}.constants.any? {{ |e| {0}.const_get(e).to_s.downcase == {1}.downcase }}",
|
||||
enumType.Name, valueReference)
|
||||
.AppendLine(
|
||||
" warn 'Enum {0} does not contain ' + {1}.downcase + ', but was received from the server.' unless enum_is_valid", enumType.Name, valueReference)
|
||||
.AppendLine("end")
|
||||
.ToString();
|
||||
}
|
||||
else if (sequence != null)
|
||||
{
|
||||
var elementVar = scope.GetUniqueName("element");
|
||||
var innerSerialization = sequence.ElementType.DeserializeType(scope, elementVar);
|
||||
|
||||
if (!string.IsNullOrEmpty(innerSerialization))
|
||||
{
|
||||
return
|
||||
builder
|
||||
.AppendLine("unless {0}.nil?", valueReference)
|
||||
.Indent()
|
||||
.AppendLine("deserialized_{0} = []", sequence.Name.ToLower())
|
||||
.AppendLine("{0}.each do |{1}|", valueReference, elementVar)
|
||||
.Indent()
|
||||
.AppendLine(innerSerialization)
|
||||
.AppendLine("deserialized_{0}.push({1})", sequence.Name.ToLower(), elementVar)
|
||||
.Outdent()
|
||||
.AppendLine("end")
|
||||
.AppendLine("{0} = deserialized_{1}", valueReference, sequence.Name.ToLower())
|
||||
.Outdent()
|
||||
.AppendLine("end")
|
||||
.ToString();
|
||||
}
|
||||
}
|
||||
else if (dictionary != null)
|
||||
{
|
||||
var valueVar = scope.GetUniqueName("valueElement");
|
||||
var innerSerialization = dictionary.ValueType.DeserializeType(scope, valueVar);
|
||||
if (!string.IsNullOrEmpty(innerSerialization))
|
||||
{
|
||||
return builder.AppendLine("unless {0}.nil?", valueReference)
|
||||
.Indent()
|
||||
.AppendLine("{0}.each do |key, {1}|", valueReference, valueVar)
|
||||
.Indent()
|
||||
.AppendLine(innerSerialization)
|
||||
.AppendLine("{0}[key] = {1}", valueReference, valueVar)
|
||||
.Outdent()
|
||||
.AppendLine("end")
|
||||
.Outdent()
|
||||
.AppendLine("end").ToString();
|
||||
}
|
||||
}
|
||||
else if (composite != null)
|
||||
{
|
||||
return builder.AppendLine("unless {0}.nil?", valueReference)
|
||||
.Indent()
|
||||
.AppendLine("{0} = {1}.deserialize_object({0})", valueReference, composite.Name)
|
||||
.Outdent()
|
||||
.AppendLine("end").ToString();
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates Ruby code in form of string for serializing object of given type.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of object needs to be serialized.</param>
|
||||
/// <param name="scope">Current scope.</param>
|
||||
/// <param name="valueReference">Reference to object which needs to serialized.</param>
|
||||
/// <returns>Generated Ruby code in form of string.</returns>
|
||||
public static string SerializeType(
|
||||
this IType type,
|
||||
IScopeProvider scope,
|
||||
string valueReference)
|
||||
{
|
||||
var composite = type as CompositeType;
|
||||
var sequence = type as SequenceType;
|
||||
var dictionary = type as DictionaryType;
|
||||
var primary = type as PrimaryType;
|
||||
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
if (primary != null)
|
||||
{
|
||||
if (primary.Type == KnownPrimaryType.ByteArray)
|
||||
{
|
||||
return builder.AppendLine("{0} = Base64.strict_encode64({0}.pack('c*'))", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.DateTime)
|
||||
{
|
||||
return builder.AppendLine("{0} = {0}.new_offset(0).strftime('%FT%TZ')", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.DateTimeRfc1123)
|
||||
{
|
||||
return builder.AppendLine("{0} = {0}.new_offset(0).strftime('%a, %d %b %Y %H:%M:%S GMT')", valueReference).ToString();
|
||||
}
|
||||
|
||||
if (primary.Type == KnownPrimaryType.UnixTime)
|
||||
{
|
||||
return builder.AppendLine("{0} = {0}.new_offset(0).strftime('%s')", valueReference).ToString();
|
||||
}
|
||||
}
|
||||
else if (sequence != null)
|
||||
{
|
||||
var elementVar = scope.GetUniqueName("element");
|
||||
var innerSerialization = sequence.ElementType.SerializeType(scope, elementVar);
|
||||
|
||||
if (!string.IsNullOrEmpty(innerSerialization))
|
||||
{
|
||||
return
|
||||
builder
|
||||
.AppendLine("unless {0}.nil?", valueReference)
|
||||
.Indent()
|
||||
.AppendLine("serialized{0} = []", sequence.Name)
|
||||
.AppendLine("{0}.each do |{1}|", valueReference, elementVar)
|
||||
.Indent()
|
||||
.AppendLine(innerSerialization)
|
||||
.AppendLine("serialized{0}.push({1})", sequence.Name.ToPascalCase(), elementVar)
|
||||
.Outdent()
|
||||
.AppendLine("end")
|
||||
.AppendLine("{0} = serialized{1}", valueReference, sequence.Name.ToPascalCase())
|
||||
.Outdent()
|
||||
.AppendLine("end")
|
||||
.ToString();
|
||||
}
|
||||
}
|
||||
else if (dictionary != null)
|
||||
{
|
||||
var valueVar = scope.GetUniqueName("valueElement");
|
||||
var innerSerialization = dictionary.ValueType.SerializeType(scope, valueVar);
|
||||
if (!string.IsNullOrEmpty(innerSerialization))
|
||||
{
|
||||
return builder.AppendLine("unless {0}.nil?", valueReference)
|
||||
.Indent()
|
||||
.AppendLine("{0}.each {{ |key, {1}|", valueReference, valueVar)
|
||||
.Indent()
|
||||
.AppendLine(innerSerialization)
|
||||
.AppendLine("{0}[key] = {1}", valueReference, valueVar)
|
||||
.Outdent()
|
||||
.AppendLine("}")
|
||||
.Outdent()
|
||||
.AppendLine("end").ToString();
|
||||
}
|
||||
}
|
||||
else if (composite != null)
|
||||
{
|
||||
return builder.AppendLine("unless {0}.nil?", valueReference)
|
||||
.Indent()
|
||||
.AppendLine("{0} = {1}.serialize_object({0})", valueReference, composite.Name)
|
||||
.Outdent()
|
||||
.AppendLine("end").ToString();
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether one composite type derives directly or indirectly from another.
|
||||
/// </summary>
|
||||
|
@ -493,5 +277,478 @@ namespace Microsoft.Rest.Generator.Ruby.TemplateModels
|
|||
(type.BaseModelType.Equals(possibleAncestorType) ||
|
||||
type.BaseModelType.DerivesFrom(possibleAncestorType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs blueprint of the given <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">Type for which mapper being generated.</param>
|
||||
/// <param name="serializedName">Serialized name to be used.</param>
|
||||
/// <param name="parameter">Parameter of the composite type to construct the parameter constraints.</param>
|
||||
/// <param name="expandComposite">Expand composite type if <c>true</c> otherwise specify class_name in the mapper.</param>
|
||||
/// <returns>Mapper for the <paramref name="type"/> as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
/// <example>
|
||||
/// One of the example of the mapper is
|
||||
/// {
|
||||
/// required: false,
|
||||
/// serialized_name: 'Fish',
|
||||
/// type: {
|
||||
/// name: 'Composite',
|
||||
/// polymorphic_discriminator: 'fishtype',
|
||||
/// uber_parent: 'Fish',
|
||||
/// class_name: 'Fish',
|
||||
/// model_properties: {
|
||||
/// species: {
|
||||
/// required: false,
|
||||
/// serialized_name: 'species',
|
||||
/// type: {
|
||||
/// name: 'String'
|
||||
/// }
|
||||
/// },
|
||||
/// length: {
|
||||
/// required: true,
|
||||
/// serialized_name: 'length',
|
||||
/// type: {
|
||||
/// name: 'Double'
|
||||
/// }
|
||||
/// },
|
||||
/// siblings: {
|
||||
/// required: false,
|
||||
/// serialized_name: 'siblings',
|
||||
/// type: {
|
||||
/// name: 'Sequence',
|
||||
/// element: {
|
||||
/// required: false,
|
||||
/// serialized_name: 'FishElementType',
|
||||
/// type: {
|
||||
/// name: 'Composite',
|
||||
/// polymorphic_discriminator: 'fishtype',
|
||||
/// uber_parent: 'Fish',
|
||||
/// class_name: 'Fish'
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// </example>
|
||||
public static string ConstructMapper(this IType type, string serializedName, IParameter parameter, bool expandComposite)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
CompositeType composite = type as CompositeType;
|
||||
SequenceType sequence = type as SequenceType;
|
||||
DictionaryType dictionary = type as DictionaryType;
|
||||
PrimaryType primary = type as PrimaryType;
|
||||
EnumType enumType = type as EnumType;
|
||||
if (enumType != null && enumType.ModelAsString)
|
||||
{
|
||||
primary = new PrimaryType(KnownPrimaryType.String);
|
||||
}
|
||||
builder.AppendLine("").Indent();
|
||||
|
||||
builder.AppendLine(type.AddMetaData(serializedName, parameter));
|
||||
|
||||
if (primary != null)
|
||||
{
|
||||
builder.AppendLine(primary.ContructMapperForPrimaryType());
|
||||
}
|
||||
else if (enumType != null && enumType.Name != null)
|
||||
{
|
||||
builder.AppendLine(enumType.ContructMapperForEnumType());
|
||||
}
|
||||
else if (sequence != null)
|
||||
{
|
||||
builder.AppendLine(sequence.ContructMapperForSequenceType());
|
||||
}
|
||||
else if (dictionary != null)
|
||||
{
|
||||
builder.AppendLine(dictionary.ContructMapperForDictionaryType());
|
||||
}
|
||||
else if (composite != null)
|
||||
{
|
||||
builder.AppendLine(composite.ContructMapperForCompositeType(expandComposite));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "{0} is not a supported Type.", type));
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds metadata to the given <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">Type for which metadata being generated.</param>
|
||||
/// <param name="serializedName">Serialized name to be used.</param>
|
||||
/// <param name="parameter">Parameter of the composite type to construct the parameter constraints.</param>
|
||||
/// <returns>Metadata as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
/// <example>
|
||||
/// The below example shows possible mapper string for IParameter for IType.
|
||||
/// required: true | false, -- whether this property is required or not
|
||||
/// read_only: true | false, -- whether this property is read only or not. Default is false
|
||||
/// is_constant: true | false, -- whether this property is constant or not. Default is false
|
||||
/// serialized_name: 'name' -- serialized name of the property if provided
|
||||
/// default_value: 'value' -- default value of the property if provided
|
||||
/// constraints: { -- constraints of the property
|
||||
/// key: value, -- constraint name and value if any
|
||||
/// ***: *****
|
||||
/// }
|
||||
/// </example>
|
||||
private static string AddMetaData(this IType type, string serializedName, IParameter parameter)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
if (serializedName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(serializedName));
|
||||
}
|
||||
|
||||
IndentedStringBuilder builder = new IndentedStringBuilder(" ");
|
||||
|
||||
Dictionary<Constraint, string> constraints = null;
|
||||
string defaultValue = null;
|
||||
bool isRequired = false;
|
||||
bool isConstant = false;
|
||||
bool isReadOnly = false;
|
||||
var property = parameter as Property;
|
||||
if (property != null)
|
||||
{
|
||||
isReadOnly = property.IsReadOnly;
|
||||
}
|
||||
if (parameter != null)
|
||||
{
|
||||
defaultValue = parameter.DefaultValue;
|
||||
isRequired = parameter.IsRequired;
|
||||
isConstant = parameter.IsConstant;
|
||||
constraints = parameter.Constraints;
|
||||
}
|
||||
|
||||
CompositeType composite = type as CompositeType;
|
||||
if (composite != null && composite.ContainsConstantProperties && isRequired)
|
||||
{
|
||||
defaultValue = "{}";
|
||||
}
|
||||
|
||||
if (isRequired)
|
||||
{
|
||||
builder.AppendLine("required: true,");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine("required: false,");
|
||||
}
|
||||
if (isReadOnly)
|
||||
{
|
||||
builder.AppendLine("read_only: true,");
|
||||
}
|
||||
if (isConstant)
|
||||
{
|
||||
builder.AppendLine("is_constant: true,");
|
||||
}
|
||||
if (serializedName != null)
|
||||
{
|
||||
builder.AppendLine("serialized_name: '{0}',", serializedName);
|
||||
}
|
||||
if (defaultValue != null)
|
||||
{
|
||||
builder.AppendLine("default_value: {0},", defaultValue);
|
||||
}
|
||||
|
||||
if (constraints != null && constraints.Count > 0)
|
||||
{
|
||||
builder.AppendLine("constraints: {").Indent();
|
||||
var keys = constraints.Keys.ToList<Constraint>();
|
||||
for (int j = 0; j < keys.Count; j++)
|
||||
{
|
||||
var constraintValue = constraints[keys[j]];
|
||||
if (keys[j] == Constraint.Pattern)
|
||||
{
|
||||
constraintValue = string.Format(CultureInfo.InvariantCulture, "'{0}'", constraintValue);
|
||||
}
|
||||
if (j != keys.Count - 1)
|
||||
{
|
||||
builder.AppendLine("{0}: {1},", keys[j], constraintValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine("{0}: {1}", keys[j], constraintValue);
|
||||
}
|
||||
}
|
||||
builder.Outdent()
|
||||
.AppendLine("},");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs blueprint of the given <paramref name="primary"/>.
|
||||
/// </summary>
|
||||
/// <param name="primary">PrimaryType for which mapper being generated.</param>
|
||||
/// <returns>Mapper for the <paramref name="primary"/> as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
/// <example>
|
||||
/// The below example shows possible mapper string for PrimaryType.
|
||||
/// type: {
|
||||
/// name: 'Boolean' -- This value should be one of the KnownPrimaryType
|
||||
/// }
|
||||
/// </example>
|
||||
private static string ContructMapperForPrimaryType(this PrimaryType primary)
|
||||
{
|
||||
if (primary == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(primary));
|
||||
}
|
||||
|
||||
IndentedStringBuilder builder = new IndentedStringBuilder(" ");
|
||||
|
||||
if (primary.Type == KnownPrimaryType.Boolean)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'Boolean'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.Double)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'Double'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.Int || primary.Type == KnownPrimaryType.Long ||
|
||||
primary.Type == KnownPrimaryType.Decimal)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'Number'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.String || primary.Type == KnownPrimaryType.Uuid)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'String'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.ByteArray)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'ByteArray'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.Base64Url)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'Base64Url'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.Date)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'Date'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.DateTime)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'DateTime'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.DateTimeRfc1123)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'DateTimeRfc1123'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.TimeSpan)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'TimeSpan'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.UnixTime)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'UnixTime'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.Object)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'Object'").Outdent().AppendLine("}");
|
||||
}
|
||||
else if (primary.Type == KnownPrimaryType.Stream)
|
||||
{
|
||||
builder.AppendLine("type: {").Indent().AppendLine("name: 'Stream'").Outdent().AppendLine("}");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "{0} is not a supported primary Type for {1}.", primary.Type, primary.SerializedName));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs blueprint of the given <paramref name="enumeration"/>.
|
||||
/// </summary>
|
||||
/// <param name="enumeration">EnumType for which mapper being generated.</param>
|
||||
/// <returns>Mapper for the <paramref name="enumeration"/> as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
/// <example>
|
||||
/// The below example shows possible mapper string for EnumType.
|
||||
/// type: {
|
||||
/// name: 'Enum',
|
||||
/// module: 'module_name' -- name of the module to be looked for enum values
|
||||
/// }
|
||||
/// </example>
|
||||
private static string ContructMapperForEnumType(this EnumType enumeration)
|
||||
{
|
||||
if (enumeration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(enumeration));
|
||||
}
|
||||
|
||||
IndentedStringBuilder builder = new IndentedStringBuilder(" ");
|
||||
|
||||
builder.AppendLine("type: {").Indent()
|
||||
.AppendLine("name: 'Enum',")
|
||||
.AppendLine("module: '{0}'", enumeration.Name).Outdent()
|
||||
.AppendLine("}");
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs blueprint of the given <paramref name="sequence"/>.
|
||||
/// </summary>
|
||||
/// <param name="sequence">SequenceType for which mapper being generated.</param>
|
||||
/// <returns>Mapper for the <paramref name="sequence"/> as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
/// <example>
|
||||
/// The below example shows possible mapper string for SequenceType.
|
||||
/// type: {
|
||||
/// name: 'Sequence',
|
||||
/// element: {
|
||||
/// *** -- mapper of the IType from the sequence element
|
||||
/// }
|
||||
/// }
|
||||
/// </example>
|
||||
private static string ContructMapperForSequenceType(this SequenceType sequence)
|
||||
{
|
||||
if (sequence == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sequence));
|
||||
}
|
||||
|
||||
IndentedStringBuilder builder = new IndentedStringBuilder(" ");
|
||||
|
||||
builder.AppendLine("type: {").Indent()
|
||||
.AppendLine("name: 'Sequence',")
|
||||
.AppendLine("element: {").Indent()
|
||||
.AppendLine("{0}", sequence.ElementType.ConstructMapper(sequence.ElementType.Name + "ElementType", null, false)).Outdent()
|
||||
.AppendLine("}").Outdent()
|
||||
.AppendLine("}");
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs blueprint of the given <paramref name="dictionary"/>.
|
||||
/// </summary>
|
||||
/// <param name="dictionary">DictionaryType for which mapper being generated.</param>
|
||||
/// <returns>Mapper for the <paramref name="dictionary"/> as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
/// <example>
|
||||
/// The below example shows possible mapper string for DictionaryType.
|
||||
/// type: {
|
||||
/// name: 'Dictionary',
|
||||
/// value: {
|
||||
/// *** -- mapper of the IType from the value type of dictionary
|
||||
/// }
|
||||
/// }
|
||||
/// </example>
|
||||
private static string ContructMapperForDictionaryType(this DictionaryType dictionary)
|
||||
{
|
||||
if (dictionary == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dictionary));
|
||||
}
|
||||
|
||||
IndentedStringBuilder builder = new IndentedStringBuilder(" ");
|
||||
|
||||
builder.AppendLine("type: {").Indent()
|
||||
.AppendLine("name: 'Dictionary',")
|
||||
.AppendLine("value: {").Indent()
|
||||
.AppendLine("{0}", dictionary.ValueType.ConstructMapper(dictionary.ValueType.Name + "ElementType", null, false)).Outdent()
|
||||
.AppendLine("}").Outdent()
|
||||
.AppendLine("}");
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs blueprint of the given <paramref name="composite"/>.
|
||||
/// </summary>
|
||||
/// <param name="composite">CompositeType for which mapper being generated.</param>
|
||||
/// <param name="expandComposite">Expand composite type if <c>true</c> otherwise specify class_name in the mapper.</param>
|
||||
/// <returns>Mapper for the <paramref name="composite"/> as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
/// <example>
|
||||
/// The below example shows possible mapper string for CompositeType.
|
||||
/// type: {
|
||||
/// name: 'Composite',
|
||||
/// polymorphic_discriminator: 'property_name', -- name of the property for polymorphic discriminator
|
||||
/// Used only when x-ms-discriminator-value applied
|
||||
/// uber_parent: 'parent_class_name', -- name of the topmost level class on inheritance hierarchy
|
||||
/// Used only when x-ms-discriminator-value applied
|
||||
/// class_name: 'class_name', -- name of the modeled class
|
||||
/// Used when <paramref name="expandComposite"/> is false
|
||||
/// model_properties: { -- expanded properties of the model
|
||||
/// Used when <paramref name="expandComposite"/> is true
|
||||
/// property_name : { -- name of the property of this composite type
|
||||
/// *** -- mapper of the IType from the type of the property
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// </example>
|
||||
private static string ContructMapperForCompositeType(this CompositeType composite, bool expandComposite)
|
||||
{
|
||||
if (composite == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(composite));
|
||||
}
|
||||
|
||||
IndentedStringBuilder builder = new IndentedStringBuilder(" ");
|
||||
|
||||
builder.AppendLine("type: {").Indent()
|
||||
.AppendLine("name: 'Composite',");
|
||||
|
||||
if (composite.PolymorphicDiscriminator != null)
|
||||
{
|
||||
builder.AppendLine("polymorphic_discriminator: '{0}',", composite.PolymorphicDiscriminator);
|
||||
var polymorphicType = composite;
|
||||
while (polymorphicType.BaseModelType != null)
|
||||
{
|
||||
polymorphicType = polymorphicType.BaseModelType;
|
||||
}
|
||||
builder.AppendLine("uber_parent: '{0}',", polymorphicType.Name);
|
||||
}
|
||||
if (!expandComposite)
|
||||
{
|
||||
builder.AppendLine("class_name: '{0}'", composite.Name).Outdent().AppendLine("}");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine("class_name: '{0}',", composite.Name)
|
||||
.AppendLine("model_properties: {").Indent();
|
||||
var composedPropertyList = new List<Property>(composite.ComposedProperties);
|
||||
for (var i = 0; i < composedPropertyList.Count; i++)
|
||||
{
|
||||
var prop = composedPropertyList[i];
|
||||
var serializedPropertyName = prop.SerializedName;
|
||||
|
||||
if (i != composedPropertyList.Count - 1)
|
||||
{
|
||||
builder.AppendLine("{0}: {{{1}}},", prop.Name, prop.Type.ConstructMapper(serializedPropertyName, prop, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine("{0}: {{{1}}}", prop.Name, prop.Type.ConstructMapper(serializedPropertyName, prop, false));
|
||||
}
|
||||
}
|
||||
// end of modelProperties and type
|
||||
builder.Outdent().
|
||||
AppendLine("}").Outdent().
|
||||
AppendLine("}");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,8 +122,11 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
/// </summary>
|
||||
public virtual IEnumerable<ParameterTemplateModel> EncodingPathParams
|
||||
{
|
||||
get { return AllPathParams.Where(p => !(p.Extensions.ContainsKey(Generator.Extensions.SkipUrlEncodingExtension) &&
|
||||
String.Equals(p.Extensions[Generator.Extensions.SkipUrlEncodingExtension].ToString(), "true", StringComparison.OrdinalIgnoreCase))); }
|
||||
get
|
||||
{
|
||||
return AllPathParams.Where(p => !(p.Extensions.ContainsKey(Generator.Extensions.SkipUrlEncodingExtension) &&
|
||||
String.Equals(p.Extensions[Generator.Extensions.SkipUrlEncodingExtension].ToString(), "true", StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -133,7 +136,7 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
{
|
||||
get
|
||||
{
|
||||
return AllPathParams.Where(p =>
|
||||
return AllPathParams.Where(p =>
|
||||
(p.Extensions.ContainsKey(Generator.Extensions.SkipUrlEncodingExtension) &&
|
||||
String.Equals(p.Extensions[Generator.Extensions.SkipUrlEncodingExtension].ToString(), "true", StringComparison.OrdinalIgnoreCase) &&
|
||||
!p.Extensions.ContainsKey("hostParameter")));
|
||||
|
@ -207,7 +210,7 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
/// Gets the list of method paramater templates.
|
||||
/// </summary>
|
||||
public List<ParameterTemplateModel> ParameterTemplateModels { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of parameter which need to be included into HTTP header.
|
||||
/// </summary>
|
||||
|
@ -271,7 +274,7 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
PrimaryType type = parameter.Type as PrimaryType;
|
||||
if (type != null)
|
||||
{
|
||||
if (type.Type == KnownPrimaryType.Boolean || type.Type == KnownPrimaryType.Double ||
|
||||
if (type.Type == KnownPrimaryType.Boolean || type.Type == KnownPrimaryType.Double ||
|
||||
type.Type == KnownPrimaryType.Int || type.Type == KnownPrimaryType.Long || type.Type == KnownPrimaryType.String)
|
||||
{
|
||||
format = "{0} = " + parameter.DefaultValue;
|
||||
|
@ -369,32 +372,12 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
builder.AppendLine("{0} = {1}.to_s.empty? ? nil : JSON.load({1})", tempVariable, inputVariable);
|
||||
|
||||
// Secondly parse each js object into appropriate Ruby type (DateTime, Byte array, etc.)
|
||||
// and overwrite temporary variable variable value.
|
||||
string deserializationLogic = type.DeserializeType(this.Scope, tempVariable);
|
||||
// and overwrite temporary variable value.
|
||||
string deserializationLogic = GetDeserializationString(type, outputVariable, tempVariable);
|
||||
builder.AppendLine(deserializationLogic);
|
||||
|
||||
// Assigning value of temporary variable to the output variable.
|
||||
return builder.AppendLine("{0} = {1}", outputVariable, tempVariable).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a code in form of string which serializes given input variable of given type.
|
||||
/// </summary>
|
||||
/// <param name="inputVariable">The input variable.</param>
|
||||
/// <param name="type">The type of input variable.</param>
|
||||
/// <param name="outputVariable">The output variable.</param>
|
||||
/// <returns>The serialization code.</returns>
|
||||
public virtual string CreateSerializationString(string inputVariable, IType type, string outputVariable)
|
||||
{
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
// Firstly recursively serialize each component of the object.
|
||||
string serializationLogic = type.SerializeType(this.Scope, inputVariable);
|
||||
|
||||
builder.AppendLine(serializationLogic);
|
||||
|
||||
// After that - generate JSON object after serializing each component.
|
||||
return builder.AppendLine("{0} = {1} != nil ? JSON.generate({1}, quirks_mode: true) : nil", outputVariable, inputVariable).ToString();
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -517,5 +500,61 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
}
|
||||
return urlPathParamName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs mapper for the request body.
|
||||
/// </summary>
|
||||
/// <param name="outputVariable">Name of the output variable.</param>
|
||||
/// <returns>Mapper for the request body as string.</returns>
|
||||
public string ConstructRequestBodyMapper(string outputVariable = "request_mapper")
|
||||
{
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
if (RequestBody.Type is CompositeType)
|
||||
{
|
||||
builder.AppendLine("{0} = {1}.mapper()", outputVariable, RequestBody.Type.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine("{0} = {{{1}}}", outputVariable,
|
||||
RequestBody.Type.ConstructMapper(RequestBody.SerializedName, RequestBody, false));
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates deserialization logic for the given <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">Type for which deserialization logic being constructed.</param>
|
||||
/// <param name="valueReference">Reference variable name.</param>
|
||||
/// <param name="responseVariable">Response variable name.</param>
|
||||
/// <returns>Deserialization logic for the given <paramref name="type"/> as string.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when a required parameter is null.</exception>
|
||||
public string GetDeserializationString(IType type, string valueReference = "result", string responseVariable = "parsed_response")
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
if (type is CompositeType)
|
||||
{
|
||||
builder.AppendLine("result_mapper = {0}.mapper()", type.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine("result_mapper = {{{0}}}", type.ConstructMapper(responseVariable, null, false));
|
||||
}
|
||||
if (Group == null)
|
||||
{
|
||||
builder.AppendLine("{1} = self.deserialize(result_mapper, {0}, '{1}')", responseVariable, valueReference);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine("{1} = @client.deserialize(result_mapper, {0}, '{1}')", responseVariable, valueReference);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,8 +4,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Rest.Generator.ClientModel;
|
||||
using Microsoft.Rest.Generator.Utilities;
|
||||
using Microsoft.Rest.Generator.Ruby.TemplateModels;
|
||||
using Microsoft.Rest.Generator.Utilities;
|
||||
|
||||
namespace Microsoft.Rest.Generator.Ruby
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
{
|
||||
get
|
||||
{
|
||||
return new List<string> {};
|
||||
return new List<string> { };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
/// </summary>
|
||||
public string PolymorphicDiscriminatorProperty
|
||||
{
|
||||
get
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.PolymorphicDiscriminator) && this.parent != null)
|
||||
{
|
||||
|
@ -124,6 +124,22 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
PropertyTemplateModels = new List<PropertyTemplateModel>();
|
||||
source.Properties.ForEach(p => PropertyTemplateModels.Add(new PropertyTemplateModel(p)));
|
||||
|
||||
if (!string.IsNullOrEmpty(source.PolymorphicDiscriminator))
|
||||
{
|
||||
if (!source.Properties.Any(p => p.Name == source.PolymorphicDiscriminator))
|
||||
{
|
||||
var polymorphicProperty = new Property
|
||||
{
|
||||
IsRequired = true,
|
||||
Name = source.PolymorphicDiscriminator,
|
||||
SerializedName = source.PolymorphicDiscriminator,
|
||||
Documentation = "Polymorhpic Discriminator",
|
||||
Type = new PrimaryType(KnownPrimaryType.String)
|
||||
};
|
||||
source.Properties.Add(polymorphicProperty);
|
||||
}
|
||||
}
|
||||
|
||||
if (source.BaseModelType != null)
|
||||
{
|
||||
this.parent = new ModelTemplateModel(source.BaseModelType, allTypes);
|
||||
|
@ -132,36 +148,6 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
this.allTypes = allTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates code for model serialization.
|
||||
/// </summary>
|
||||
/// <param name="variableName">Variable serialize model from.</param>
|
||||
/// <param name="type">The type of the model.</param>
|
||||
/// <returns>The code for serialization in string format.</returns>
|
||||
public virtual string SerializeProperty(string variableName, IType type)
|
||||
{
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
string serializationLogic = type.SerializeType(this.Scope, variableName);
|
||||
builder.AppendLine(serializationLogic);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates code for model deserialization.
|
||||
/// </summary>
|
||||
/// <param name="variableName">Variable deserialize model from.</param>
|
||||
/// <param name="type">The type of the model.</param>
|
||||
/// <returns>The code for вуserialization in string format.</returns>
|
||||
public virtual string DeserializeProperty(string variableName, IType type)
|
||||
{
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
|
||||
string serializationLogic = type.DeserializeType(this.Scope, variableName);
|
||||
return builder.AppendLine(serializationLogic).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns code for declaring inheritance.
|
||||
/// </summary>
|
||||
|
@ -170,5 +156,17 @@ namespace Microsoft.Rest.Generator.Ruby
|
|||
{
|
||||
return this.BaseModelType != null ? " < " + this.BaseModelType.Name : string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs mapper for the model class.
|
||||
/// </summary>
|
||||
/// <returns>Mapper as string for this model class.</returns>
|
||||
public virtual string ConstructModelMapper()
|
||||
{
|
||||
var modelMapper = this.ConstructMapper(SerializedName, null, true);
|
||||
var builder = new IndentedStringBuilder(" ");
|
||||
builder.AppendLine("{{{0}}}", modelMapper);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -95,11 +95,7 @@ def @(Model.Name)_async(@(Model.MethodParameterDeclaration))
|
|||
if (parameter.IsConstant)
|
||||
{
|
||||
@:@(parameter.Name) = @(parameter.DefaultValue)
|
||||
}
|
||||
else
|
||||
{
|
||||
@:@(parameter.Type.ValidateType(Model.Scope, parameter.Name))
|
||||
}
|
||||
}
|
||||
}
|
||||
request_headers = {}
|
||||
@if (Model.Parameters.Any(p => p.Location == ParameterLocation.Header))
|
||||
|
@ -120,9 +116,13 @@ def @(Model.Name)_async(@(Model.MethodParameterDeclaration))
|
|||
@if (Model.RequestBody != null)
|
||||
{
|
||||
@EmptyLine
|
||||
@:# Serialize Request
|
||||
@:request_headers['Content-Type'] = '@(Model.RequestContentType)'
|
||||
@:@Model.CreateSerializationString(Model.RequestBody.Name, Model.RequestBody.Type, "request_content")
|
||||
@EmptyLine
|
||||
@:# Serialize Request
|
||||
@:@Model.ConstructRequestBodyMapper("request_mapper")
|
||||
@:request_content = @(Model.ClientReference).serialize(request_mapper, @(Model.RequestBody.Name), '@(Model.RequestBody.Name)')
|
||||
@:request_content = request_content != nil ? JSON.generate(request_content, quirks_mode: true) : nil
|
||||
@EmptyLine
|
||||
}
|
||||
|
||||
path_template = '@Model.Url'
|
||||
|
|
|
@ -31,7 +31,18 @@ module @(Settings.Namespace)
|
|||
@:@@@@discriminatorMap["@derivedType.SerializedName"] = "@derivedType.Name.ToLowerInvariant()"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@if (Model.IsPolymorphic)
|
||||
{
|
||||
@EmptyLine
|
||||
@:def initialize
|
||||
@: @@@Model.PolymorphicDiscriminatorProperty = "@Model.SerializedName"
|
||||
@:end
|
||||
@EmptyLine
|
||||
@:attr_accessor :@Model.PolymorphicDiscriminatorProperty
|
||||
@EmptyLine
|
||||
}
|
||||
|
||||
@foreach (var property in Model.PropertyTemplateModels)
|
||||
{
|
||||
@:@WrapComment("# ", string.Format("@return {0}{1}", property.Type.GetYardDocumentation(), property.Documentation))
|
||||
|
@ -41,115 +52,14 @@ module @(Settings.Namespace)
|
|||
@:
|
||||
}
|
||||
|
||||
@EmptyLine
|
||||
#
|
||||
# Validate the object. Throws ValidationError if validation fails.
|
||||
@WrapComment("# ", string.Format("Mapper for {0} class as Ruby Hash.", Model.Name))
|
||||
# This will be used for serialization/deserialization.
|
||||
#
|
||||
def validate
|
||||
@{
|
||||
bool anythingToValidate = false;
|
||||
foreach (var property in Model.Properties.Where(p => p.IsRequired && !p.IsReadOnly && p.Type.IsNullable()))
|
||||
{
|
||||
anythingToValidate = true;
|
||||
@:fail MsRest::ValidationError, 'property @property.Name is nil' if @@@(property.Name).nil?
|
||||
}
|
||||
foreach (var property in Model.Properties.Where(p => !(p.Type is PrimaryType)))
|
||||
{
|
||||
anythingToValidate = true;
|
||||
@:@property.Type.ValidateType(Model.Scope, string.Format("@{0}", property.Name))
|
||||
@:
|
||||
}
|
||||
if (!anythingToValidate)
|
||||
{
|
||||
@:# Nothing to validate
|
||||
}
|
||||
}
|
||||
def self.mapper()
|
||||
@(Model.ConstructModelMapper())
|
||||
end
|
||||
|
||||
@EmptyLine
|
||||
#
|
||||
# Serializes given Model object into Ruby Hash.
|
||||
@WrapComment("# ", string.Format("@param {0} {1}", "object", "Model object to serialize."))
|
||||
@WrapComment("# ", string.Format("@return [Hash] {0}", "Serialized object in form of Ruby Hash."))
|
||||
#
|
||||
def self.serialize_object(object)
|
||||
object.validate
|
||||
output_object = {}
|
||||
|
||||
@if (Model.IsPolymorphic)
|
||||
{
|
||||
@EmptyLine
|
||||
@:unless object.@(Model.PolymorphicDiscriminatorProperty).nil? or object.@(Model.PolymorphicDiscriminatorProperty) == "@Model.SerializedName"
|
||||
@:class_name = @@@@discriminatorMap[object.@Model.PolymorphicDiscriminatorProperty].capitalize
|
||||
@:class_instance = Models.const_get(class_name)
|
||||
@foreach (var ns in Model.ClassNamespaces)
|
||||
{
|
||||
@:class_instance = @(ns).const_get(class_name) if class_instance.nil?
|
||||
}
|
||||
@:output_object = class_instance.serialize_object(object)
|
||||
@:else
|
||||
@:output_object['@Model.PolymorphicDiscriminatorProperty'] = object.@Model.PolymorphicDiscriminatorProperty
|
||||
@:end
|
||||
}
|
||||
|
||||
@foreach (var property in Model.ComposedProperties.OrderByDescending(x => x.IsRequired))
|
||||
{
|
||||
@EmptyLine
|
||||
@:serialized_property = @("object." + property.Name)
|
||||
@:@Model.SerializeProperty("serialized_property", property.Type)
|
||||
@:output_object['@(property.SerializedName)'] = serialized_property unless serialized_property.nil?
|
||||
}
|
||||
|
||||
@EmptyLine
|
||||
output_object
|
||||
end
|
||||
|
||||
@EmptyLine
|
||||
#
|
||||
# Deserializes given Ruby Hash into Model object.
|
||||
@WrapComment("# ", string.Format("@param {0} [Hash] {1}", "object", "Ruby Hash object to deserialize."))
|
||||
@WrapComment("# ", string.Format("@return [{0}] {1}", Model.Name, "Deserialized object."))
|
||||
#
|
||||
def self.deserialize_object(object)
|
||||
return if object.nil?
|
||||
output_object = @(Model.Name).new
|
||||
|
||||
@if (Model.IsPolymorphic)
|
||||
{
|
||||
@EmptyLine
|
||||
@:unless object['@(Model.PolymorphicDiscriminatorProperty)'].nil? or object['@(Model.PolymorphicDiscriminatorProperty)'] == "@Model.SerializedName"
|
||||
@:class_name = @@@@discriminatorMap[object['@Model.PolymorphicDiscriminatorProperty']].capitalize
|
||||
@:class_instance = Models.const_get(class_name)
|
||||
@foreach (var ns in Model.ClassNamespaces)
|
||||
{
|
||||
@:class_instance = @(ns).const_get(class_name) if class_instance.nil?
|
||||
}
|
||||
@:output_object = class_instance.deserialize_object(object)
|
||||
@:else
|
||||
@:output_object.@Model.PolymorphicDiscriminatorProperty = object['@Model.PolymorphicDiscriminatorProperty']
|
||||
@:end
|
||||
}
|
||||
|
||||
@foreach (var property in Model.ComposedProperties.OrderByDescending(x => x.IsRequired))
|
||||
{
|
||||
@EmptyLine
|
||||
@:deserialized_property = @(string.Format("object['{0}']", property.SerializedName))
|
||||
@:@Model.DeserializeProperty("deserialized_property", property.Type)
|
||||
@:output_object.@(property.Name) = deserialized_property
|
||||
}
|
||||
|
||||
@EmptyLine
|
||||
output_object
|
||||
end
|
||||
|
||||
@if (Model.IsPolymorphic)
|
||||
{
|
||||
@EmptyLine
|
||||
@:def initialize
|
||||
@: @@@Model.PolymorphicDiscriminatorProperty = "@Model.SerializedName"
|
||||
@:end
|
||||
@EmptyLine
|
||||
@:attr_accessor :@Model.PolymorphicDiscriminatorProperty
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ module @Settings.Namespace
|
|||
{
|
||||
@:include @(Settings.Namespace)::Models
|
||||
}
|
||||
include MsRest::Serialization
|
||||
@foreach (var include in Model.Includes)
|
||||
{
|
||||
@:include @include
|
||||
|
|
|
@ -23,67 +23,61 @@ module MsRestAzure
|
|||
# @return [Hash{String => String}] the tags attached to resources (optional).
|
||||
attr_accessor :tags
|
||||
|
||||
#
|
||||
# Serializes given resource object into hash.
|
||||
# @param object [Resource] resource object to serialize.
|
||||
#
|
||||
# @return [Hash] hash representation of resource.
|
||||
def self.serialize_object(object)
|
||||
object.validate
|
||||
output_object = {}
|
||||
|
||||
serialized_property = object.id
|
||||
output_object['id'] = serialized_property unless serialized_property.nil?
|
||||
|
||||
serialized_property = object.name
|
||||
output_object['name'] = serialized_property unless serialized_property.nil?
|
||||
|
||||
serialized_property = object.type
|
||||
output_object['type'] = serialized_property unless serialized_property.nil?
|
||||
|
||||
serialized_property = object.location
|
||||
output_object['location'] = serialized_property unless serialized_property.nil?
|
||||
|
||||
serialized_property = object.tags
|
||||
output_object['tags'] = serialized_property unless serialized_property.nil?
|
||||
|
||||
output_object
|
||||
def self.mapper
|
||||
{
|
||||
required: false,
|
||||
serialized_name: 'Resource',
|
||||
type: {
|
||||
name: 'Composite',
|
||||
class_name: 'Resource',
|
||||
model_properties: {
|
||||
id: {
|
||||
required: false,
|
||||
serialized_name: 'id',
|
||||
type: {
|
||||
name: 'String'
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
read_only: true,
|
||||
serialized_name: 'name',
|
||||
type: {
|
||||
name: 'String'
|
||||
}
|
||||
},
|
||||
type: {
|
||||
required: false,
|
||||
read_only: true,
|
||||
serialized_name: 'type',
|
||||
type: {
|
||||
name: 'String'
|
||||
}
|
||||
},
|
||||
location: {
|
||||
required: false,
|
||||
serialized_name: 'location',
|
||||
type: {
|
||||
name: 'String'
|
||||
}
|
||||
},
|
||||
tags: {
|
||||
required: false,
|
||||
serialized_name: 'tags',
|
||||
type: {
|
||||
name: 'Dictionary',
|
||||
value: {
|
||||
required: false,
|
||||
serialized_name: 'StringElementType',
|
||||
type: {
|
||||
name: 'String'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Deserializes given hash object into resource.
|
||||
# @param object [Hash] resource in hash representation to deserialize.
|
||||
#
|
||||
# @return [Resource] deserialized resource.
|
||||
def self.deserialize_object(object)
|
||||
return if object.nil?
|
||||
output_object = Resource.new
|
||||
|
||||
deserialized_property = object['id']
|
||||
output_object.id = deserialized_property
|
||||
|
||||
deserialized_property = object['name']
|
||||
output_object.name = deserialized_property
|
||||
|
||||
deserialized_property = object['type']
|
||||
output_object.type = deserialized_property
|
||||
|
||||
deserialized_property = object['location']
|
||||
output_object.location = deserialized_property
|
||||
|
||||
deserialized_property = object['tags']
|
||||
output_object.tags = deserialized_property
|
||||
|
||||
output_object.validate
|
||||
output_object
|
||||
end
|
||||
|
||||
#
|
||||
# Validates the resource. Throws error if there is any property is incorrect.
|
||||
#
|
||||
def validate
|
||||
fail MsRest::ValidationError, 'Location cannot be nil in the Resource object' if @location.nil?
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,41 +11,24 @@ module MsRestAzure
|
|||
# @return [String] the id of the subresource.
|
||||
attr_accessor :id
|
||||
|
||||
#
|
||||
# Serializes given subresource object into hash.
|
||||
# @param object [SubResource] subresource object to serialize.
|
||||
#
|
||||
# @return [Hash] hash representation of subresource.
|
||||
def self.serialize_object(object)
|
||||
object.validate
|
||||
output_object = {}
|
||||
|
||||
serialized_property = object.id
|
||||
output_object['id'] = serialized_property unless serialized_property.nil?
|
||||
|
||||
output_object
|
||||
end
|
||||
|
||||
#
|
||||
# Deserializes given hash object into subresource.
|
||||
# @param object [Hash] subresource in hash representation to deserialize.
|
||||
#
|
||||
# @return [SubResource] deserialized subresource.
|
||||
def self.deserialize_object(object)
|
||||
return if object.nil?
|
||||
output_object = SubResource.new
|
||||
|
||||
deserialized_property = object['id']
|
||||
output_object.id = deserialized_property
|
||||
|
||||
output_object.validate
|
||||
output_object
|
||||
end
|
||||
|
||||
#
|
||||
# Validates the subresource. Throws error if there is any property is incorrect.
|
||||
#
|
||||
def validate
|
||||
def self.mapper
|
||||
{
|
||||
required: false,
|
||||
serialized_name: 'SubResource',
|
||||
type: {
|
||||
name: 'Composite',
|
||||
class_name: 'SubResource',
|
||||
model_properties: {
|
||||
id: {
|
||||
required: false,
|
||||
serialized_name: 'id',
|
||||
type: {
|
||||
name: 'String'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,8 +6,15 @@ require 'rspec'
|
|||
require 'ms_rest_azure'
|
||||
|
||||
module MsRestAzure
|
||||
class Helper
|
||||
include MsRest::Serialization
|
||||
end
|
||||
|
||||
describe Resource do
|
||||
before (:all) do
|
||||
@helper = Helper.new
|
||||
end
|
||||
|
||||
it 'should serialize Resource correctly' do
|
||||
resource = Resource.new
|
||||
resource.id = 'id'
|
||||
|
@ -19,7 +26,8 @@ module MsRestAzure
|
|||
'tag2' => 'tag2_value'
|
||||
}
|
||||
|
||||
res = Resource.serialize_object(resource)
|
||||
allow_any_instance_of(MsRest::Serialization::Serialization).to receive(:get_model).and_return(Resource)
|
||||
res = @helper.serialize(Resource.mapper(), resource, 'resource')
|
||||
|
||||
expect(res).to be_a(Hash)
|
||||
expect(res['id']).to eq('id')
|
||||
|
@ -41,7 +49,8 @@ module MsRestAzure
|
|||
}
|
||||
}
|
||||
|
||||
res = Resource.deserialize_object(resource_hash)
|
||||
allow_any_instance_of(MsRest::Serialization::Serialization).to receive(:get_model).and_return(Resource)
|
||||
res = @helper.deserialize(Resource.mapper(), resource_hash, 'resource_hash')
|
||||
|
||||
expect(res).to be_a(Resource)
|
||||
expect(res.id).to eq('id')
|
||||
|
@ -50,16 +59,5 @@ module MsRestAzure
|
|||
expect(res.location).to eq('location')
|
||||
expect(res.tags).to eq({ 'tag1' => 'tag1_value', 'tag2' => 'tag2_value' })
|
||||
end
|
||||
|
||||
it 'should throw error if location isn\'t provided' do
|
||||
resource_hash = {
|
||||
'id' => 'id',
|
||||
'name' => 'name',
|
||||
'type' => 'type'
|
||||
}
|
||||
|
||||
expect { Resource.deserialize_object(resource_hash) }.to raise_error(MsRest::ValidationError)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -6,13 +6,21 @@ require 'rspec'
|
|||
require 'ms_rest_azure'
|
||||
|
||||
module MsRestAzure
|
||||
class Helper
|
||||
include MsRest::Serialization
|
||||
end
|
||||
|
||||
describe SubResource do
|
||||
before (:all) do
|
||||
@helper = Helper.new
|
||||
end
|
||||
|
||||
it 'should serialize SubResource correctly' do
|
||||
sub_resource = SubResource.new
|
||||
sub_resource.id = 'the_id'
|
||||
|
||||
sub_resource_serialized = SubResource.serialize_object(sub_resource)
|
||||
allow_any_instance_of(MsRest::Serialization::Serialization).to receive(:get_model).and_return(SubResource)
|
||||
sub_resource_serialized = @helper.serialize(SubResource.mapper(), sub_resource, 'sub_resource')
|
||||
|
||||
expect(sub_resource_serialized).to be_a(Hash)
|
||||
expect(sub_resource_serialized['id']).to eq('the_id')
|
||||
|
@ -22,12 +30,11 @@ module MsRestAzure
|
|||
sub_resource_hash = {
|
||||
'id' => 'the_id'
|
||||
}
|
||||
|
||||
sub_resource = SubResource.deserialize_object(sub_resource_hash)
|
||||
allow_any_instance_of(MsRest::Serialization::Serialization).to receive(:get_model).and_return(SubResource)
|
||||
sub_resource = @helper.deserialize(SubResource.mapper(), sub_resource_hash, 'sub_resource_hash')
|
||||
|
||||
expect(sub_resource).to be_a(SubResource)
|
||||
expect(sub_resource.id).to eq('the_id')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -24,4 +24,5 @@ require 'ms_rest/http_operation_error'
|
|||
require 'ms_rest/retry_policy_middleware'
|
||||
require 'ms_rest/service_client'
|
||||
|
||||
module MsRest; end
|
||||
module MsRest end
|
||||
module MsRest::Serialization end
|
||||
|
|
|
@ -3,20 +3,364 @@
|
|||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
module MsRest
|
||||
# Base module for Ruby serialization and deserialization.
|
||||
#
|
||||
# Class which keeps the auxiliary for (de)serializing JSON requests and responses from server.
|
||||
#
|
||||
class Serialization
|
||||
# Provides methods to serialize Ruby object into Ruby Hash and
|
||||
# to deserialize Ruby Hash into Ruby object.
|
||||
module Serialization
|
||||
#
|
||||
# Deserialize the response from the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the response_body.
|
||||
# @param response_body [Hash] Ruby Hash object to deserialize.
|
||||
# @param object_name [String] Name of the deserialized object.
|
||||
#
|
||||
def deserialize(mapper, response_body, object_name)
|
||||
serialization = Serialization.new(self)
|
||||
serialization.deserialize(mapper, response_body, object_name)
|
||||
end
|
||||
|
||||
#
|
||||
# Deserializes given string value into Ruby Date object.
|
||||
# @param [String] string_value string value to deserialize.
|
||||
# Serialize the Ruby object into Ruby Hash to send it to the server using the mapper.
|
||||
#
|
||||
# @return [Date] deserialized Date object.
|
||||
def self.deserialize_date(string_value)
|
||||
result = Timeliness.parse(string_value, :strict => true)
|
||||
fail DeserializationError.new('Error occured in deserializing the response', nil, nil, string_value) if result.nil?
|
||||
return ::Date.parse(result.to_s)
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the object.
|
||||
# @param object [Object] Ruby object to serialize.
|
||||
# @param object_name [String] Name of the serialized object.
|
||||
#
|
||||
def serialize(mapper, object, object_name)
|
||||
serialization = Serialization.new(self)
|
||||
serialization.serialize(mapper, object, object_name)
|
||||
end
|
||||
|
||||
#
|
||||
# Class to handle serialization & deserialization.
|
||||
#
|
||||
class Serialization
|
||||
def initialize(context)
|
||||
@context = context
|
||||
end
|
||||
|
||||
#
|
||||
# Deserialize the response from the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the response_body.
|
||||
# @param response_body [Hash] Ruby Hash object to deserialize.
|
||||
# @param object_name [String] Name of the deserialized object.
|
||||
#
|
||||
def deserialize(mapper, response_body, object_name)
|
||||
return response_body if response_body.nil?
|
||||
|
||||
object_name = mapper[:serialized_name] unless object_name.nil?
|
||||
mapper_type = mapper[:type][:name]
|
||||
|
||||
if !mapper_type.match(/^(Number|Double|ByteArray|Boolean|Date|DateTime|DateTimeRfc1123|UnixTime|Enum|String|Object|Stream)$/i).nil?
|
||||
payload = deserialize_primary_type(mapper, response_body)
|
||||
elsif !mapper_type.match(/^Dictionary$/i).nil?
|
||||
payload = deserialize_dictionary_type(mapper, response_body, object_name)
|
||||
elsif !mapper_type.match(/^Composite$/i).nil?
|
||||
payload = deserialize_composite_type(mapper, response_body, object_name)
|
||||
elsif !mapper_type.match(/^Sequence$/i).nil?
|
||||
payload = deserialize_sequence_type(mapper, response_body, object_name)
|
||||
else
|
||||
payload = ""
|
||||
end
|
||||
|
||||
payload = mapper[:default_value] if mapper[:is_constant]
|
||||
|
||||
payload
|
||||
end
|
||||
|
||||
#
|
||||
# Deserialize the response of known primary type from the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the response_body.
|
||||
# @param response_body [Hash] Ruby Hash object to deserialize.
|
||||
#
|
||||
def deserialize_primary_type(mapper, response_body)
|
||||
result = ""
|
||||
case mapper[:type][:name]
|
||||
when 'Number'
|
||||
result = Integer(response_body) unless response_body.to_s.empty?
|
||||
when 'Double'
|
||||
result = Float(response_body) unless response_body.to_s.empty?
|
||||
when 'ByteArray'
|
||||
result = Base64.strict_decode64(response_body).unpack('C*') unless response_body.to_s.empty?
|
||||
when 'String', 'Boolean', 'Object', 'Stream'
|
||||
result = response_body
|
||||
when 'Enum'
|
||||
unless response_body.nil? || response_body.empty?
|
||||
unless enum_is_valid(mapper, response_body)
|
||||
warn "Enum #{model} does not contain #{response_body.downcase}, but was received from the server."
|
||||
end
|
||||
end
|
||||
result = response_body
|
||||
when 'Date'
|
||||
unless response_body.to_s.empty?
|
||||
result = Timeliness.parse(response_body, :strict => true)
|
||||
fail DeserializationError.new('Error occured in deserializing the response_body', nil, nil, response_body) if result.nil?
|
||||
result = ::Date.parse(result.to_s)
|
||||
end
|
||||
when 'DateTime', 'DateTimeRfc1123'
|
||||
result = DateTime.parse(response_body) unless response_body.to_s.empty?
|
||||
when 'UnixTime'
|
||||
result = DateTime.strptime(response_body.to_s, '%s') unless response_body.to_s.empty?
|
||||
else
|
||||
result
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
#
|
||||
# Deserialize the response of dictionary type from the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the response_body.
|
||||
# @param response_body [Hash] Ruby Hash object to deserialize.
|
||||
# @param object_name [String] Name of the deserialized object.
|
||||
#
|
||||
def deserialize_dictionary_type(mapper, response_body, object_name)
|
||||
if mapper[:type][:value].nil? || !mapper[:type][:value].is_a?(Hash)
|
||||
fail DeserializationError.new("'value' metadata for a dictionary type must be defined in the mapper and it must be of type Hash in #{object_name}", nil, nil, response_body)
|
||||
end
|
||||
|
||||
result = Hash.new
|
||||
response_body.each do |key, val|
|
||||
result[key] = deserialize(mapper[:type][:value], val, object_name)
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
#
|
||||
# Deserialize the response of composite type from the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the response_body.
|
||||
# @param response_body [Hash] Ruby Hash object to deserialize.
|
||||
# @param object_name [String] Name of the deserialized object.
|
||||
#
|
||||
def deserialize_composite_type(mapper, response_body, object_name)
|
||||
if mapper[:type][:class_name].nil?
|
||||
fail DeserializationError.new("'class_name' metadata for a composite type must be defined in the mapper and it must be of type Hash in #{object_name}", nil, nil, response_body)
|
||||
end
|
||||
|
||||
if !mapper[:type][:polymorphic_discriminator].nil?
|
||||
# Handle polymorphic types
|
||||
parent_class = get_model(mapper[:type][:class_name])
|
||||
discriminator = parent_class.class_eval("@@discriminatorMap")
|
||||
model_name = response_body["#{mapper[:type][:polymorphic_discriminator]}"]
|
||||
model_class = get_model(discriminator[model_name].capitalize)
|
||||
else
|
||||
model_class = get_model(mapper[:type][:class_name])
|
||||
end
|
||||
|
||||
result = model_class.new
|
||||
|
||||
model_mapper = model_class.mapper()
|
||||
model_props = model_mapper[:type][:model_properties]
|
||||
|
||||
unless model_props.nil?
|
||||
model_props.each do |key, val|
|
||||
result.instance_variable_set("@#{key}", deserialize(val, response_body[val[:serialized_name].to_s], object_name))
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
#
|
||||
# Deserialize the response of sequence type from the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the response_body.
|
||||
# @param response_body [Hash] Ruby Hash object to deserialize.
|
||||
# @param object_name [String] Name of the deserialized object.
|
||||
#
|
||||
def deserialize_sequence_type(mapper, response_body, object_name)
|
||||
if mapper[:type][:element].nil? || !mapper[:type][:element].is_a?(Hash)
|
||||
fail DeserializationError.new("'element' metadata for a sequence type must be defined in the mapper and it must be of type Hash in #{object_name}", nil, nil, response_body)
|
||||
end
|
||||
|
||||
return response_body if response_body.nil?
|
||||
|
||||
result = []
|
||||
response_body.each do |element|
|
||||
result.push(deserialize(mapper[:type][:element], element, object_name))
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
#
|
||||
# Serialize the Ruby object into Ruby Hash to send it to the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the object.
|
||||
# @param object [Object] Ruby object to serialize.
|
||||
# @param object_name [String] Name of the serialized object.
|
||||
#
|
||||
def serialize(mapper, object, object_name)
|
||||
object_name = mapper[:serialized_name] unless object_name.nil?
|
||||
|
||||
if mapper[:required] && object.nil? && !mapper[:is_constant]
|
||||
fail ValidationError, "#{object_name} is required and cannot be nil"
|
||||
end
|
||||
|
||||
if !mapper[:required] && object.nil?
|
||||
return object
|
||||
end
|
||||
|
||||
# Set defaults
|
||||
unless mapper[:default_value].nil?
|
||||
object = mapper[:default_value] if object.nil?
|
||||
end
|
||||
object = mapper[:default_value] if mapper[:is_constant]
|
||||
|
||||
payload = Hash.new
|
||||
mapper_type = mapper[:type][:name]
|
||||
if !mapper_type.match(/^(Number|Double|ByteArray|Boolean|Date|DateTime|DateTimeRfc1123|UnixTime|Enum|String|Object|Stream)$/i).nil?
|
||||
payload = serialize_primary_type(mapper, object)
|
||||
elsif !mapper_type.match(/^Dictionary$/i).nil?
|
||||
payload = serialize_dictionary_type(mapper, object, object_name)
|
||||
elsif !mapper_type.match(/^Composite$/i).nil?
|
||||
payload = serialize_composite_type(mapper, object, object_name)
|
||||
elsif !mapper_type.match(/^Sequence$/i).nil?
|
||||
payload = serialize_sequence_type(mapper, object, object_name)
|
||||
end
|
||||
payload
|
||||
end
|
||||
|
||||
#
|
||||
# Serialize the Ruby object of known primary type into Ruby Hash to send it to the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the object.
|
||||
# @param object [Object] Ruby object to serialize.
|
||||
#
|
||||
def serialize_primary_type(mapper, object)
|
||||
mapper_type = mapper[:type][:name]
|
||||
payload = nil
|
||||
case mapper_type
|
||||
when 'Number', 'Double', 'String', 'Date', 'Boolean', 'Object', 'Stream'
|
||||
payload = object != nil ? object : nil
|
||||
when 'Enum'
|
||||
unless object.nil? || object.empty?
|
||||
unless enum_is_valid(mapper, object)
|
||||
fail ValidationError, "Enum #{mapper[:type][:module]} does not contain #{object.to_s}, but trying to send it to the server."
|
||||
end
|
||||
end
|
||||
payload = object != nil ? object : nil
|
||||
when 'ByteArray'
|
||||
payload = Base64.strict_encode64(object.pack('c*'))
|
||||
when 'DateTime'
|
||||
payload = object.new_offset(0).strftime('%FT%TZ')
|
||||
when 'DateTimeRfc1123'
|
||||
payload = object.new_offset(0).strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||
when 'UnixTime'
|
||||
payload = object.new_offset(0).strftime('%s') unless object.nil?
|
||||
end
|
||||
payload
|
||||
end
|
||||
|
||||
#
|
||||
# Serialize the Ruby object of dictionary type into Ruby Hash to send it to the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the object.
|
||||
# @param object [Object] Ruby object to serialize.
|
||||
# @param object_name [String] Name of the serialized object.
|
||||
#
|
||||
def serialize_dictionary_type(mapper, object, object_name)
|
||||
unless object.is_a?(Hash)
|
||||
fail DeserializationError.new("#{object_name} must be of type Hash", nil, nil, object)
|
||||
end
|
||||
|
||||
unless mapper[:type][:value].nil? || mapper[:type][:value].is_a?(Hash)
|
||||
fail DeserializationError.new("'value' metadata for a dictionary type must be defined in the mapper and it must be of type Hash in #{object_name}", nil, nil, object)
|
||||
end
|
||||
|
||||
payload = Hash.new
|
||||
object.each do |key, value|
|
||||
if !value.nil? && value.respond_to?(:validate)
|
||||
value.validate
|
||||
end
|
||||
|
||||
payload[key] = serialize(mapper[:type][:value], value, object_name)
|
||||
end
|
||||
payload
|
||||
end
|
||||
|
||||
#
|
||||
# Serialize the Ruby object of composite type into Ruby Hash to send it to the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the object.
|
||||
# @param object [Object] Ruby object to serialize.
|
||||
# @param object_name [String] Name of the serialized object.
|
||||
#
|
||||
def serialize_composite_type(mapper, object, object_name)
|
||||
if !mapper[:type][:polymorphic_discriminator].nil?
|
||||
# Handle polymorphic types
|
||||
model_name = object.class.to_s.split('::')[-1]
|
||||
model_class = get_model(model_name)
|
||||
else
|
||||
model_class = get_model(mapper[:type][:class_name])
|
||||
end
|
||||
|
||||
payload = Hash.new
|
||||
model_mapper = model_class.mapper()
|
||||
model_props = model_mapper[:type][:model_properties]
|
||||
|
||||
unless model_props.nil?
|
||||
model_props.each do |key, value|
|
||||
instance_variable = object.instance_variable_get("@#{key}")
|
||||
if !instance_variable.nil? && instance_variable.respond_to?(:validate)
|
||||
instance_variable.validate
|
||||
end
|
||||
|
||||
sub_payload = serialize(value, instance_variable, object_name)
|
||||
payload[value[:serialized_name].to_s] = sub_payload unless instance_variable.nil?
|
||||
end
|
||||
end
|
||||
payload
|
||||
end
|
||||
|
||||
#
|
||||
# Serialize the Ruby object of sequence type into Ruby Hash to send it to the server using the mapper.
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object to represent expected structure of the object.
|
||||
# @param object [Object] Ruby object to serialize.
|
||||
# @param object_name [String] Name of the serialized object.
|
||||
#
|
||||
def serialize_sequence_type(mapper, object, object_name)
|
||||
unless object.is_a?(Array)
|
||||
fail DeserializationError.new("#{object_name} must be of type of Array", nil, nil, object)
|
||||
end
|
||||
|
||||
unless mapper[:type][:element].nil? || mapper[:type][:element].is_a?(Hash)
|
||||
fail DeserializationError.new("'element' metadata for a sequence type must be defined in the mapper and it must be of type Hash in #{object_name}", nil, nil, object)
|
||||
end
|
||||
|
||||
payload = Array.new
|
||||
object.each do |element|
|
||||
if !element.nil? && element.respond_to?(:validate)
|
||||
element.validate
|
||||
end
|
||||
payload.push(serialize(mapper[:type][:element], element, object_name))
|
||||
end
|
||||
payload
|
||||
end
|
||||
|
||||
#
|
||||
# Retrieves model of the model_name
|
||||
#
|
||||
# @param model_name [String] Name of the model to retrieve.
|
||||
#
|
||||
def get_model(model_name)
|
||||
Object.const_get(@context.class.to_s.split('::')[0...-1].join('::') + "::Models::#{model_name}")
|
||||
end
|
||||
|
||||
#
|
||||
# Checks whether given enum_value is valid for the mapper or not
|
||||
#
|
||||
# @param mapper [Hash] Ruby Hash object containing meta data
|
||||
# @param enum_value [String] Enum value to validate
|
||||
#
|
||||
def enum_is_valid(mapper, enum_value)
|
||||
model = get_model(mapper[:type][:module])
|
||||
model.constants.any? { |e| model.const_get(e).to_s.downcase == enum_value.downcase }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
# encoding: utf-8
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
require 'rspec'
|
||||
require 'ms_rest'
|
||||
|
||||
module MsRest
|
||||
|
||||
describe Serialization do
|
||||
it 'should parse correct date' do
|
||||
parsed_date = Serialization.deserialize_date('1/1/2000')
|
||||
expect(parsed_date).to eq(Date.new(2000, 1, 1))
|
||||
end
|
||||
|
||||
it 'should throw error if incorrect date is provided' do
|
||||
expect { Serialization.deserialize_date('13/1/2000') }.to raise_error(DeserializationError)
|
||||
end
|
||||
|
||||
it 'should throw error if incorrect date format is provided' do
|
||||
expect { Serialization.deserialize_date('invalid_date') }.to raise_error(DeserializationError)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Загрузка…
Ссылка в новой задаче