From a213bac448e2543339694a6dbca6d2edef787701 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sun, 8 Sep 2019 20:46:20 +1200 Subject: [PATCH] Fix deserialize via ctor with some existing collection types (#2151) --- .../JsonSerializerCollectionsTests.cs | 23 +++++++++++++++++++ .../JsonSerializerInternalReader.cs | 15 ++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerCollectionsTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerCollectionsTests.cs index c3678e56..631cd6ec 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerCollectionsTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerCollectionsTests.cs @@ -62,6 +62,29 @@ namespace Newtonsoft.Json.Tests.Serialization public class JsonSerializerCollectionsTests : TestFixtureBase { #if !(NET35 || NET20 || PORTABLE || PORTABLE40) || NETSTANDARD2_0 + [Test] + public void DeserializeNonGenericListTypeAndReadOnlyListViaConstructor() + { + ConstructorCollectionContainer a = JsonConvert.DeserializeObject("{'a':1,'b':['aaa'],'c':['aaa']}"); + + Assert.AreEqual(1, a.A); + Assert.AreEqual(1, a.B.Count()); + Assert.AreEqual("aaa", a.B.ElementAt(0)); + Assert.AreEqual(0, a.C.Count()); + } + + public class ConstructorCollectionContainer + { + public int A { get; } + public IEnumerable B { get; } = new SortedSet(); + public IEnumerable C { get; } = new List().AsReadOnly(); + + public ConstructorCollectionContainer(int a) + { + this.A = a; + } + } + [Test] public void DeserializeConcurrentDictionaryWithNullValue() { diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 7b6c9ed3..5cb82550 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -2079,12 +2079,19 @@ namespace Newtonsoft.Json.Serialization object? createdObjectCollection = property.ValueProvider!.GetValue(createdObject); if (createdObjectCollection != null) { - IList createdObjectCollectionWrapper = (propertyArrayContract.ShouldCreateWrapper) ? propertyArrayContract.CreateWrapper(createdObjectCollection) : (IList)createdObjectCollection; - IList newValues = (propertyArrayContract.ShouldCreateWrapper) ? propertyArrayContract.CreateWrapper(value) : (IList)value; + propertyArrayContract = (JsonArrayContract)GetContract(createdObjectCollection.GetType()); - foreach (object newValue in newValues) + IList createdObjectCollectionWrapper = (propertyArrayContract.ShouldCreateWrapper) ? propertyArrayContract.CreateWrapper(createdObjectCollection) : (IList)createdObjectCollection; + + // Don't attempt to populate array/read-only list + if (!createdObjectCollectionWrapper.IsFixedSize) { - createdObjectCollectionWrapper.Add(newValue); + IList newValues = (propertyArrayContract.ShouldCreateWrapper) ? propertyArrayContract.CreateWrapper(value) : (IList)value; + + foreach (object newValue in newValues) + { + createdObjectCollectionWrapper.Add(newValue); + } } } }