diff --git a/RestSharp.Tests/XmlTests.cs b/RestSharp.Tests/XmlTests.cs index 8a3b15a2e..f01e26f90 100644 --- a/RestSharp.Tests/XmlTests.cs +++ b/RestSharp.Tests/XmlTests.cs @@ -640,7 +640,42 @@ 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(response); + Assert.Equal(DateTimeOffset, payload.DateTimeOffset); + Assert.Null(payload.NullableDateTimeOffsetWithNull); + + Assert.True(payload.NullableDateTimeOffsetWithValue.HasValue); + Assert.Equal(NullableDateTimeOffsetWithValue, payload.NullableDateTimeOffsetWithValue); + } private static string CreateUnderscoresXml() { @@ -934,5 +969,6 @@ private static string CreateXmlWithAttributesAndNullValuesAndPopulatedValues() return doc.ToString(); } + } } diff --git a/RestSharp/Deserializers/XmlAttributeDeserializer.cs b/RestSharp/Deserializers/XmlAttributeDeserializer.cs index 8d7ca4f8b..9b3f9bec6 100644 --- a/RestSharp/Deserializers/XmlAttributeDeserializer.cs +++ b/RestSharp/Deserializers/XmlAttributeDeserializer.cs @@ -55,7 +55,7 @@ public T Deserialize(IRestResponse response) RemoveNamespace(doc); } - var x = Activator.CreateInstance(); + var x = Activator.CreateInstance(); var objType = x.GetType(); if (objType.IsSubclassOfRawGeneric(typeof(List<>))) diff --git a/RestSharp/Deserializers/XmlDeserializer.cs b/RestSharp/Deserializers/XmlDeserializer.cs index 346290ce1..4d85080a3 100644 --- a/RestSharp/Deserializers/XmlDeserializer.cs +++ b/RestSharp/Deserializers/XmlDeserializer.cs @@ -22,7 +22,8 @@ using RestSharp.Extensions; using System.Globalization; -using System.Xml; +using System.Xml; +using System.ComponentModel; namespace RestSharp.Deserializers { @@ -168,7 +169,34 @@ 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)) { value = Decimal.Parse(value.ToString(), Culture); @@ -209,20 +237,41 @@ 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 elements, IList list) {