From 4fc0ad5d53804bc0be2e9d679938eb960f09cd5e Mon Sep 17 00:00:00 2001 From: Eamon Hetherton Date: Fri, 8 Feb 2013 08:43:51 +1000 Subject: [PATCH 1/6] Add support for DateTimeOffset to XmlDeserializer --- RestSharp/Deserializers/XmlDeserializer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/RestSharp/Deserializers/XmlDeserializer.cs b/RestSharp/Deserializers/XmlDeserializer.cs index 346290ce1..392eb721b 100644 --- a/RestSharp/Deserializers/XmlDeserializer.cs +++ b/RestSharp/Deserializers/XmlDeserializer.cs @@ -168,7 +168,12 @@ private void Map(object x, XElement root) } prop.SetValue(x, value, null); - } + } + else if (type == typeof(DateTimeOffset)) + { + var toConvert = value.ToString(); + prop.SetValue(x, XmlConvert.ToDateTimeOffset(toConvert), null); + } else if (type == typeof(Decimal)) { value = Decimal.Parse(value.ToString(), Culture); From 2d411a55d2431fca5a9e5ba10a458082b24c81a0 Mon Sep 17 00:00:00 2001 From: Eamon Hetherton Date: Fri, 8 Feb 2013 08:51:55 +1000 Subject: [PATCH 2/6] Ignore empty string values --- RestSharp/Deserializers/XmlDeserializer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RestSharp/Deserializers/XmlDeserializer.cs b/RestSharp/Deserializers/XmlDeserializer.cs index 392eb721b..83c21838d 100644 --- a/RestSharp/Deserializers/XmlDeserializer.cs +++ b/RestSharp/Deserializers/XmlDeserializer.cs @@ -172,7 +172,10 @@ private void Map(object x, XElement root) else if (type == typeof(DateTimeOffset)) { var toConvert = value.ToString(); - prop.SetValue(x, XmlConvert.ToDateTimeOffset(toConvert), null); + if (!string.IsNullOrEmpty(toConvert)) + { + prop.SetValue(x, XmlConvert.ToDateTimeOffset(toConvert), null); + } } else if (type == typeof(Decimal)) { From a1f25c77d40aca462166324b3f76941a7298019f Mon Sep 17 00:00:00 2001 From: Eamon Hetherton Date: Fri, 8 Feb 2013 08:56:48 +1000 Subject: [PATCH 3/6] Add TypeConverter fallback option --- RestSharp/Deserializers/XmlDeserializer.cs | 46 ++++++++++++++++------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/RestSharp/Deserializers/XmlDeserializer.cs b/RestSharp/Deserializers/XmlDeserializer.cs index 83c21838d..36cb54709 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 { @@ -217,20 +218,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, value, 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) { From ed7540a486c5086a00f1207fea40c5f611ebbb8b Mon Sep 17 00:00:00 2001 From: Eamon Hetherton Date: Fri, 8 Feb 2013 09:21:46 +1000 Subject: [PATCH 4/6] Added unit Test for DateTimeOffset XmlDeserialization --- RestSharp.Tests/XmlTests.cs | 38 ++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) 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(); } + } } From 9789dd6055a10e17871c1c81455fc8541d5d6c8c Mon Sep 17 00:00:00 2001 From: Eamon Hetherton Date: Fri, 8 Mar 2013 09:14:46 +1000 Subject: [PATCH 5/6] added fallback option for datetimeoffset objects that can't be deserialised by XmlConvert --- RestSharp/Deserializers/XmlDeserializer.cs | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/RestSharp/Deserializers/XmlDeserializer.cs b/RestSharp/Deserializers/XmlDeserializer.cs index 36cb54709..4d85080a3 100644 --- a/RestSharp/Deserializers/XmlDeserializer.cs +++ b/RestSharp/Deserializers/XmlDeserializer.cs @@ -175,7 +175,26 @@ private void Map(object x, XElement root) var toConvert = value.ToString(); if (!string.IsNullOrEmpty(toConvert)) { - prop.SetValue(x, XmlConvert.ToDateTimeOffset(toConvert), null); + 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)) @@ -223,7 +242,7 @@ private void Map(object x, XElement root) object result; if (TryGetFromString(value.ToString(), out result, type)) { - prop.SetValue(x, value, null); + prop.SetValue(x, result, null); } else { From 7de5465d486773d7c9934e98b16f11ddf3b17e54 Mon Sep 17 00:00:00 2001 From: Eamon Hetherton Date: Thu, 5 Sep 2013 08:56:44 +1000 Subject: [PATCH 6/6] Fixed Indentation --- RestSharp/Deserializers/XmlAttributeDeserializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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<>)))