diff --git a/src/RestSharp/Parameters/ObjectParser.cs b/src/RestSharp/Parameters/ObjectParser.cs index 9076fdc6e..bde6c33f4 100644 --- a/src/RestSharp/Parameters/ObjectParser.cs +++ b/src/RestSharp/Parameters/ObjectParser.cs @@ -23,34 +23,45 @@ static class ObjectParser { var type = obj.GetType(); var props = type.GetProperties(); + var properties = new List<(string Name, string? Value)>(); + foreach (var prop in props.Where(x => IsAllowedProperty(x.Name))) { var val = prop.GetValue(obj, null); if (val == null) continue; - yield return prop.PropertyType.IsArray - ? GetArray(prop, val) - : GetValue(prop, val); + if (prop.PropertyType.IsArray) + properties.AddRange(GetArray(prop, val)); + else + properties.Add(GetValue(prop, val)); } string? ParseValue(string? format, object? value) => format == null ? value?.ToString() : string.Format($"{{0:{format}}}", value); - (string, string?) GetArray(PropertyInfo propertyInfo, object? value) { + IEnumerable<(string, string?)> GetArray(PropertyInfo propertyInfo, object? value) { var elementType = propertyInfo.PropertyType.GetElementType(); var array = (Array)value!; var attribute = propertyInfo.GetCustomAttribute(); var name = attribute?.Name ?? propertyInfo.Name; + var queryType = attribute?.ArrayQueryType ?? RequestArrayQueryType.CommaSeparated; + if (array.Length > 0 && elementType != null) { // convert the array to an array of strings var values = array .Cast() .Select(item => ParseValue(attribute?.Format, item)); - return (name, string.Join(",", values)); + + return queryType switch { + RequestArrayQueryType.CommaSeparated => new (string, string?)[] { (name, string.Join(",", values)) }, + RequestArrayQueryType.ArrayParameters => values.Select(x => ($"{name}[]", x)), + _ => throw new ArgumentOutOfRangeException() + }; + } - return (name, null); + return new (string, string?)[] { (name, null) }; } (string, string?) GetValue(PropertyInfo propertyInfo, object? value) { @@ -62,12 +73,16 @@ static class ObjectParser { bool IsAllowedProperty(string propertyName) => includedProperties.Length == 0 || includedProperties.Length > 0 && includedProperties.Contains(propertyName); + + return properties; } } [AttributeUsage(AttributeTargets.Property)] public class RequestPropertyAttribute : Attribute { - public string? Name { get; set; } - - public string? Format { get; set; } + public string? Name { get; set; } + public string? Format { get; set; } + public RequestArrayQueryType ArrayQueryType { get; set; } = RequestArrayQueryType.CommaSeparated; } + +public enum RequestArrayQueryType { CommaSeparated, ArrayParameters } diff --git a/test/RestSharp.Tests/ObjectParserTests.cs b/test/RestSharp.Tests/ObjectParserTests.cs index 8c0c3097b..0df8b17a0 100644 --- a/test/RestSharp.Tests/ObjectParserTests.cs +++ b/test/RestSharp.Tests/ObjectParserTests.cs @@ -7,6 +7,7 @@ public class ObjectParserTests { public void ShouldUseRequestProperty() { var now = DateTime.Now; var dates = new[] { now, now.AddDays(1), now.AddDays(2) }; + var request = new TestObject { SomeData = "test", SomeDate = now, @@ -24,17 +25,33 @@ public class ObjectParserTests { parsed["dates"].Should().Be(string.Join(",", dates.Select(x => x.ToString("d")))); } + [Fact] + public void ShouldProduceMultipleParametersForArray() { + var request = new AnotherTestObject { + SomeIds = new[] { 1, 2, 3 } + }; + var expected = request.SomeIds.Select(x => ("ids[]", x.ToString())); + var parsed = request.GetProperties(); + + parsed.Should().BeEquivalentTo(expected); + } + + class AnotherTestObject { + [RequestProperty(Name = "ids", ArrayQueryType = RequestArrayQueryType.ArrayParameters)] + public int[] SomeIds { get; set; } + } + class TestObject { [RequestProperty(Name = "some_data")] public string SomeData { get; set; } [RequestProperty(Format = "d")] public DateTime SomeDate { get; set; } - + [RequestProperty(Name = "dates", Format = "d")] public DateTime[] DatesArray { get; set; } - public int Plain { get; set; } + public int Plain { get; set; } public DateTime[] PlainArray { get; set; } } }