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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 82 additions & 46 deletions RestSharp.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,47 +254,47 @@ public void Can_Deserialize_Elements_to_Nullable_Values()
Assert.Equal(new Guid(GuidString), output.UniqueId);
}

[Fact]
public void Can_Deserialize_TimeSpan()
{
var culture = CultureInfo.InvariantCulture;
var doc = new XDocument(culture);

TimeSpan? nullTimespan = null;
TimeSpan? nullValueTimeSpan = new TimeSpan(21, 30, 7);

var root = new XElement("Person");
root.Add(new XElement("Tick", new TimeSpan(468006)));
root.Add(new XElement("Millisecond", new TimeSpan(0, 0, 0, 0, 125)));
root.Add(new XElement("Second", new TimeSpan(0, 0, 8)));
root.Add(new XElement("Minute", new TimeSpan(0, 55, 2)));
root.Add(new XElement("Hour", new TimeSpan(21, 30, 7)));
root.Add(new XElement("NullableWithoutValue", nullTimespan));
root.Add(new XElement("NullableWithValue", nullValueTimeSpan));

doc.Add(root);

var xml = new XmlDeserializer
{
Culture = culture,
};

var response = new RestResponse { Content = doc.ToString() };

var d = new XmlDeserializer()
{
Culture = culture,
};
var payload = d.Deserialize<TimeSpanTestStructure>(response);
Assert.Equal(new TimeSpan(468006), payload.Tick);
Assert.Equal(new TimeSpan(0, 0, 0, 0, 125), payload.Millisecond);
Assert.Equal(new TimeSpan(0, 0, 8), payload.Second);
Assert.Equal(new TimeSpan(0, 55, 2), payload.Minute);
Assert.Equal(new TimeSpan(21, 30, 7), payload.Hour);
Assert.Null(payload.NullableWithoutValue);
Assert.NotNull(payload.NullableWithValue);
Assert.Equal(new TimeSpan(21, 30, 7), payload.NullableWithValue.Value);
}
[Fact]
public void Can_Deserialize_TimeSpan()
{
var culture = CultureInfo.InvariantCulture;
var doc = new XDocument(culture);

TimeSpan? nullTimespan = null;
TimeSpan? nullValueTimeSpan = new TimeSpan(21, 30, 7);

var root = new XElement("Person");
root.Add(new XElement("Tick", new TimeSpan(468006)));
root.Add(new XElement("Millisecond", new TimeSpan(0, 0, 0, 0, 125)));
root.Add(new XElement("Second", new TimeSpan(0, 0, 8)));
root.Add(new XElement("Minute", new TimeSpan(0, 55, 2)));
root.Add(new XElement("Hour", new TimeSpan(21, 30, 7)));
root.Add(new XElement("NullableWithoutValue", nullTimespan));
root.Add(new XElement("NullableWithValue", nullValueTimeSpan));

doc.Add(root);

var xml = new XmlDeserializer
{
Culture = culture,
};

var response = new RestResponse { Content = doc.ToString() };

var d = new XmlDeserializer()
{
Culture = culture,
};
var payload = d.Deserialize<TimeSpanTestStructure>(response);
Assert.Equal(new TimeSpan(468006), payload.Tick);
Assert.Equal(new TimeSpan(0, 0, 0, 0, 125), payload.Millisecond);
Assert.Equal(new TimeSpan(0, 0, 8), payload.Second);
Assert.Equal(new TimeSpan(0, 55, 2), payload.Minute);
Assert.Equal(new TimeSpan(21, 30, 7), payload.Hour);
Assert.Null(payload.NullableWithoutValue);
Assert.NotNull(payload.NullableWithValue);
Assert.Equal(new TimeSpan(21, 30, 7), payload.NullableWithValue.Value);
}

[Fact]
public void Can_Deserialize_Custom_Formatted_Date()
Expand Down Expand Up @@ -496,8 +496,8 @@ public void Can_Deserialize_Names_With_Underscores_Without_Matching_Case_On_Defa
Assert.Equal (5, p.Foes.Count);
Assert.Equal ("Yankees", p.Foes.Team);
}
[Fact]
[Fact]
public void Can_Deserialize_Lower_Cased_Root_Elements_With_Dashes()
{
var doc = CreateDashesXml();
Expand Down Expand Up @@ -640,6 +640,41 @@ public void Can_Deserialize_Mixture_Of_Empty_Elements_With_Attributes_And_Popula
Assert.Null(output.Id);
Assert.Null(output.StartDate);
Assert.Equal(new Guid(GuidString), output.UniqueId);
}

[Fact]
public void Can_Deserialize_DateTimeOffset()
{
var culture = CultureInfo.InvariantCulture;
var doc = new XDocument(culture);

DateTimeOffset DateTimeOffset = new DateTimeOffset(2013, 02, 08, 9, 18, 22, TimeSpan.FromHours(10));
DateTimeOffset? NullableDateTimeOffsetWithValue = new DateTimeOffset(2013, 02, 08, 9, 18, 23, TimeSpan.FromHours(10));

var root = new XElement("Dates");
root.Add(new XElement("DateTimeOffset", DateTimeOffset));
root.Add(new XElement("NullableDateTimeOffsetWithNull", string.Empty));
root.Add(new XElement("NullableDateTimeOffsetWithValue", NullableDateTimeOffsetWithValue));

doc.Add(root);

var xml = new XmlDeserializer
{
Culture = culture,
};

var response = new RestResponse { Content = doc.ToString() };

var d = new XmlDeserializer()
{
Culture = culture,
};
var payload = d.Deserialize<DateTimeTestStructure>(response);
Assert.Equal(DateTimeOffset, payload.DateTimeOffset);
Assert.Null(payload.NullableDateTimeOffsetWithNull);

Assert.True(payload.NullableDateTimeOffsetWithValue.HasValue);
Assert.Equal(NullableDateTimeOffsetWithValue, payload.NullableDateTimeOffsetWithValue);
}

private static string CreateUnderscoresXml()
Expand Down Expand Up @@ -771,10 +806,10 @@ private static string CreateDashesXml()
doc.Add(root);
return doc.ToString();
}
private static string CreateLowerCasedRootElementWithDashesXml()
private static string CreateLowerCasedRootElementWithDashesXml()
{
var doc = new XDocument();
var doc = new XDocument();
var root = new XElement("incoming-invoices",
new XElement("incoming-invoice",
new XElement("concept-id", 45)
Expand Down Expand Up @@ -934,5 +969,6 @@ private static string CreateXmlWithAttributesAndNullValuesAndPopulatedValues()

return doc.ToString();
}

}
}
2 changes: 1 addition & 1 deletion RestSharp/Deserializers/XmlAttributeDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public T Deserialize<T>(IRestResponse response)
RemoveNamespace(doc);
}

var x = Activator.CreateInstance<T>();
var x = Activator.CreateInstance<T>();
var objType = x.GetType();

if (objType.IsSubclassOfRawGeneric(typeof(List<>)))
Expand Down
97 changes: 73 additions & 24 deletions RestSharp/Deserializers/XmlDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@

using RestSharp.Extensions;
using System.Globalization;
using System.Xml;
using System.Xml;
using System.ComponentModel;

namespace RestSharp.Deserializers
{
Expand Down Expand Up @@ -124,13 +125,13 @@ private void Map(object x, XElement root)
// check for nullable and extract underlying type
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// if the value is empty, set the property to null...
if (value == null || String.IsNullOrEmpty(value.ToString()))
{
prop.SetValue(x, null, null);
continue;
}
type = type.GetGenericArguments()[0];
// if the value is empty, set the property to null...
if (value == null || String.IsNullOrEmpty(value.ToString()))
{
prop.SetValue(x, null, null);
continue;
}
type = type.GetGenericArguments()[0];
}

if (type == typeof(bool))
Expand Down Expand Up @@ -168,6 +169,33 @@ private void Map(object x, XElement root)
}

prop.SetValue(x, value, null);
}
else if (type == typeof(DateTimeOffset))
{
var toConvert = value.ToString();
if (!string.IsNullOrEmpty(toConvert))
{
DateTimeOffset deserialisedValue;
try
{
deserialisedValue = XmlConvert.ToDateTimeOffset(toConvert);
prop.SetValue(x, deserialisedValue, null);
}
catch (Exception)
{
object result;
if (TryGetFromString(toConvert, out result, type))
{
prop.SetValue(x, result, null);
}
else
{
//fallback to parse
deserialisedValue = DateTimeOffset.Parse(toConvert);
prop.SetValue(x, deserialisedValue, null);
}
}
}
}
else if (type == typeof(Decimal))
{
Expand All @@ -179,12 +207,12 @@ private void Map(object x, XElement root)
var raw = value.ToString();
value = string.IsNullOrEmpty(raw) ? Guid.Empty : new Guid(value.ToString());
prop.SetValue(x, value, null);
}
else if (type == typeof(TimeSpan))
{
var timeSpan = XmlConvert.ToTimeSpan(value.ToString());
prop.SetValue(x, timeSpan, null);
}
}
else if (type == typeof(TimeSpan))
{
var timeSpan = XmlConvert.ToTimeSpan(value.ToString());
prop.SetValue(x, timeSpan, null);
}
else if (type.IsGenericType)
{
var t = type.GetGenericArguments()[0];
Expand All @@ -209,19 +237,40 @@ private void Map(object x, XElement root)
prop.SetValue(x, list, null);
}
else
{
// nested property classes
if (root != null)
{
var element = GetElementByName(root, name);
if (element != null)
{
var item = CreateAndMap(type, element);
prop.SetValue(x, item, null);
}
{
//fallback to type converters if possible
object result;
if (TryGetFromString(value.ToString(), out result, type))
{
prop.SetValue(x, result, null);
}
else
{
// nested property classes
if (root != null)
{
var element = GetElementByName(root, name);
if (element != null)
{
var item = CreateAndMap(type, element);
prop.SetValue(x, item, null);
}
}
}
}
}
}

private static bool TryGetFromString(string inputString, out object result, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
if (converter.CanConvertFrom(typeof(string)))
{
result = (converter.ConvertFromInvariantString(inputString));
return true;
}
result = null;
return false;
}

private void PopulateListFromElements(Type t, IEnumerable<XElement> elements, IList list)
Expand Down