From a5b7507d173923aedd07c71d3a5e25708c232ba7 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Sat, 3 Oct 2009 07:54:47 +0000 Subject: [PATCH] -Fixed List silly buggers with nullable types - http://tinyurl.com/yagsptj - That was tough! --- .../Serialization/JsonSerializerTest.cs | 11 +++++++++++ .../Serialization/JsonSerializerInternalReader.cs | 12 +++++++----- Src/Newtonsoft.Json/Utilities/CollectionUtils.cs | 6 +++--- Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs | 7 +++++-- Src/Newtonsoft.Json/Utilities/ListWrapper.cs | 7 +++++-- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 0b6f0d51..a0d0dcbe 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -2227,5 +2227,16 @@ keyword such as type of business."" list l = JsonConvert.DeserializeObject(json); } + + [Test] + public void sdfsdf() + { + //List l = new List(); + //l.Add(null); + //IList il = l; + //il.Add(null); + + JsonConvert.DeserializeObject>("[ 3.3, null, 1.1 ] "); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 0fee2dcf..fa7ea463 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -502,12 +502,14 @@ namespace Newtonsoft.Json.Serialization throw new JsonSerializationException("Cannot call OnError on an array or readonly list: {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); #endif - PopulateList(l, reader, reference, contract); + PopulateList(CollectionUtils.CreateCollectionWrapper(l), reader, reference, contract); }); } - private IList PopulateList(IList list, JsonReader reader, string reference, JsonArrayContract contract) + private object PopulateList(IWrappedCollection wrappedList, JsonReader reader, string reference, JsonArrayContract contract) { + object list = wrappedList.UnderlyingCollection; + if (reference != null) _serializer.ReferenceResolver.AddReference(reference, list); @@ -522,7 +524,7 @@ namespace Newtonsoft.Json.Serialization case JsonToken.EndArray: contract.InvokeOnDeserialized(list); - return list; + return wrappedList.UnderlyingCollection; case JsonToken.Comment: break; default: @@ -530,12 +532,12 @@ namespace Newtonsoft.Json.Serialization { object value = CreateValue(reader, contract.CollectionItemType, null, null); - list.Add(value); + wrappedList.Add(value); } catch (Exception ex) { #if !PocketPC && !SILVERLIGHT && !NET20 - ErrorContext errorContext = GetErrorContext(list, list.Count, ex); + ErrorContext errorContext = GetErrorContext(list, wrappedList.Count, ex); contract.InvokeOnError(list, errorContext); if (errorContext.Handled) diff --git a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs index d6e03adc..2025f2e9 100644 --- a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs @@ -525,7 +525,7 @@ namespace Newtonsoft.Json.Utilities // can't add or modify a readonly list // use List and convert once populated - list = (IList)CreateGenericList(readOnlyCollectionContentsType); + list = CreateGenericList(readOnlyCollectionContentsType); isReadOnlyOrFixedSize = true; } else if (typeof(IList).IsAssignableFrom(listType)) @@ -537,9 +537,9 @@ namespace Newtonsoft.Json.Utilities else list = null; } - else if (listType.IsGenericType && listType.GetGenericTypeDefinition() == typeof(IList<>)) + else if (ReflectionUtils.ImplementsGenericDefinition(listType, typeof(IList<>))) { - list = CollectionUtils.CreateGenericList(ReflectionUtils.GetCollectionItemType(listType)); + list = CreateGenericList(ReflectionUtils.GetCollectionItemType(listType)); } else { diff --git a/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs b/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs index 0346aafd..1eb45353 100644 --- a/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs +++ b/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs @@ -48,7 +48,10 @@ namespace Newtonsoft.Json.Utilities { ValidationUtils.ArgumentNotNull(list, "list"); - _list = list; + if (list is ICollection) + _genericCollection = (ICollection)list; + else + _list = list; } public CollectionWrapper(ICollection list) @@ -248,7 +251,7 @@ namespace Newtonsoft.Json.Utilities private static bool IsCompatibleObject(object value) { - if (!(value is T) && (value != null || typeof(T).IsValueType)) + if (!(value is T) && (value != null || (typeof(T).IsValueType && !ReflectionUtils.IsNullableType(typeof(T))))) return false; return true; diff --git a/Src/Newtonsoft.Json/Utilities/ListWrapper.cs b/Src/Newtonsoft.Json/Utilities/ListWrapper.cs index 014362fa..a485fabf 100644 --- a/Src/Newtonsoft.Json/Utilities/ListWrapper.cs +++ b/Src/Newtonsoft.Json/Utilities/ListWrapper.cs @@ -48,7 +48,10 @@ namespace Newtonsoft.Json.Utilities { ValidationUtils.ArgumentNotNull(list, "list"); - _list = list; + if (list is IList) + _genericList = (IList) list; + else + _list = list; } public ListWrapper(IList list) @@ -267,7 +270,7 @@ namespace Newtonsoft.Json.Utilities private static bool IsCompatibleObject(object value) { - if (!(value is T) && (value != null || typeof(T).IsValueType)) + if (!(value is T) && (value != null || (typeof(T).IsValueType && !ReflectionUtils.IsNullableType(typeof(T))))) return false; return true;