diff options
author | Miguel de Icaza <miguel@gnome.org> | 2011-11-24 10:29:20 +0400 |
---|---|---|
committer | Miguel de Icaza <miguel@gnome.org> | 2011-11-24 10:29:27 +0400 |
commit | 88e2387665a651bea38bac81f9a86a6c338b6977 (patch) | |
tree | 1c7e5e2fe22219c11726532f9cb9b7d804e57662 /mcs/class/System.ServiceModel.Web | |
parent | e731bbd4617a17412ab65edaf5108c498e6dd5c3 (diff) |
Extend JsonSerializerReader to support nullables and parse a wider range of Date formats, fixes x#163
Diffstat (limited to 'mcs/class/System.ServiceModel.Web')
2 files changed, 49 insertions, 1 deletions
diff --git a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs index 9daa8820181..3a5e57ff125 100644 --- a/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs +++ b/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs @@ -72,6 +72,9 @@ namespace System.Runtime.Serialization.Json if (serialized_object_count ++ == serializer.MaxItemsInObjectGraph) throw SerializationError (String.Format ("The object graph exceeded the maximum object count '{0}' specified in the serializer", serializer.MaxItemsInObjectGraph)); + if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>)) + type = Nullable.GetUnderlyingType (type); + bool isNull = reader.GetAttribute ("type") == "null"; switch (Type.GetTypeCode (type)) { @@ -121,7 +124,29 @@ namespace System.Runtime.Serialization.Json var s = reader.ReadElementContentAsString (); if (s.Length < 2 || !s.StartsWith ("/Date(", StringComparison.Ordinal) || !s.EndsWith (")/", StringComparison.Ordinal)) throw new XmlException ("Invalid JSON DateTime format. The value format should be '/Date(UnixTime)/'"); - return new DateTime (1970, 1, 1).AddMilliseconds (long.Parse (s.Substring (6, s.Length - 8))); + + // The date can contain [SIGN]LONG, [SIGN]LONG+HOURSMINUTES or [SIGN]LONG-HOURSMINUTES + // the format for HOURSMINUTES is DDDD + int tidx = s.IndexOf ('-', 8); + if (tidx == -1) + tidx = s.IndexOf ('+', 8); + int minutes = 0; + if (tidx == -1){ + s = s.Substring (6, s.Length - 8); + } else { + int offset; + int.TryParse (s.Substring (tidx+1, s.Length-3-tidx), out offset); + + minutes = (offset % 100) + (offset / 100) * 60; + if (s [tidx] == '-') + minutes = -minutes; + + s = s.Substring (6, tidx-6); + } + var date = new DateTime (1970, 1, 1).AddMilliseconds (long.Parse (s)); + if (minutes != 0) + date = date.AddMinutes (minutes); + return date; default: if (type == typeof (Guid)) { return new Guid (reader.ReadElementContentAsString ()); diff --git a/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs b/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs index 3debe78edb1..2a75876fd0d 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs +++ b/mcs/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs @@ -1362,6 +1362,29 @@ namespace MonoTests.System.Runtime.Serialization.Json Assert.AreEqual (query.StartDate, q.StartDate, "#2"); Assert.AreEqual (query.EndDate, q.EndDate, "#3"); } + + [DataContract(Name = "DateTest")] + public class DateTest + { + [DataMember(Name = "should_have_value")] + public DateTime? ShouldHaveValue { get; set; } + } + + // + // This tests both the extended format "number-0500" as well + // as the nullable field in the structure + [Test] + public void BugXamarin163 () + { + string json = @"{""should_have_value"":""\/Date(1277355600000-0500)\/""}"; + + byte[] bytes = global::System.Text.Encoding.UTF8.GetBytes(json); + Stream inputStream = new MemoryStream(bytes); + + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(DateTest)); + DateTest t = serializer.ReadObject(inputStream) as DateTest; + Assert.AreEqual (634129344000000000, t.ShouldHaveValue.Value.Ticks, "#1"); + } [Test] public void DeserializeNullMember () |