-Fixed error attempting to deserialize into read-only collections from non-default constructor
This commit is contained in:
@@ -24,7 +24,9 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Schema;
|
||||
@@ -50,7 +52,6 @@ using Test = Xunit.FactAttribute;
|
||||
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
|
||||
#else
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1636,30 +1637,51 @@ namespace Newtonsoft.Json.Tests
|
||||
public void ShouldNotPopulateReadOnlyEnumerableObjectWithNonDefaultConstructor()
|
||||
{
|
||||
object actual = JsonConvert.DeserializeObject<HasReadOnlyEnumerableObject>("{\"foo\":{}}");
|
||||
Assert.NotNull(actual);
|
||||
Assert.IsNotNull(actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldNotPopulateReadOnlyEnumerableObjectWithDefaultConstructor()
|
||||
{
|
||||
object actual = JsonConvert.DeserializeObject<HasReadOnlyEnumerableObjectAndDefaultConstructor>("{\"foo\":{}}");
|
||||
Assert.NotNull(actual);
|
||||
Assert.IsNotNull(actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldNotPopulateContructorArgumentEnumerableObject()
|
||||
{
|
||||
object actual = JsonConvert.DeserializeObject<AcceptsEnumerableObjectToConstructor>("{\"foo\":{}}");
|
||||
Assert.NotNull(actual);
|
||||
Assert.IsNotNull(actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldNotPopulateEnumerableObjectProperty()
|
||||
{
|
||||
object actual = JsonConvert.DeserializeObject<HasEnumerableObject>("{\"foo\":{}}");
|
||||
Assert.NotNull(actual);
|
||||
Assert.IsNotNull(actual);
|
||||
}
|
||||
|
||||
#if !(NET40 || NET35 || NET20)
|
||||
[Test]
|
||||
public void ShouldNotPopulateReadOnlyDictionaryObjectWithNonDefaultConstructor()
|
||||
{
|
||||
object actual = JsonConvert.DeserializeObject<HasReadOnlyDictionary>("{\"foo\":{'key':'value'}}");
|
||||
Assert.IsNotNull(actual);
|
||||
}
|
||||
|
||||
public sealed class HasReadOnlyDictionary
|
||||
{
|
||||
[JsonProperty("foo")]
|
||||
public IReadOnlyDictionary<string, string> Foo { get; } = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>());
|
||||
|
||||
[JsonConstructor]
|
||||
public HasReadOnlyDictionary([JsonProperty("bar")] int bar)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public sealed class HasReadOnlyEnumerableObject
|
||||
{
|
||||
[JsonProperty("foo")]
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='netcoreapp1.0'">
|
||||
<PackageReference Include="FSharp.Core" Version="4.1.0" />
|
||||
<PackageReference Include="System.ObjectModel" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Xml" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
|
||||
|
||||
@@ -5031,7 +5031,7 @@ Path '', line 1, position 1.");
|
||||
JsonTypeReflector.SetFullyTrusted(false);
|
||||
|
||||
JsonConvert.DeserializeObject<ISerializableTestObject>("{booleanValue:true}");
|
||||
}, @"Type 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ISerializableTestObject' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine +
|
||||
}, @"Type 'Newtonsoft.Json.Tests.Serialization.ISerializableTestObject' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine +
|
||||
@"To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine +
|
||||
@"Path 'booleanValue', line 1, position 14.");
|
||||
}
|
||||
@@ -5052,7 +5052,7 @@ Path '', line 1, position 1.");
|
||||
ISerializableTestObject value = new ISerializableTestObject("string!", 0, default(DateTimeOffset), null);
|
||||
|
||||
JsonConvert.SerializeObject(value);
|
||||
}, @"Type 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ISerializableTestObject' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine +
|
||||
}, @"Type 'Newtonsoft.Json.Tests.Serialization.ISerializableTestObject' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine +
|
||||
@"To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine +
|
||||
@"Path ''.");
|
||||
}
|
||||
|
||||
@@ -2032,15 +2032,18 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
JsonArrayContract propertyArrayContract = (JsonArrayContract)propertyContract;
|
||||
|
||||
object createdObjectCollection = property.ValueProvider.GetValue(createdObject);
|
||||
if (createdObjectCollection != null)
|
||||
if (propertyArrayContract.CanDeserialize)
|
||||
{
|
||||
IWrappedCollection createdObjectCollectionWrapper = propertyArrayContract.CreateWrapper(createdObjectCollection);
|
||||
IWrappedCollection newValues = propertyArrayContract.CreateWrapper(value);
|
||||
|
||||
foreach (object newValue in newValues)
|
||||
object createdObjectCollection = property.ValueProvider.GetValue(createdObject);
|
||||
if (createdObjectCollection != null)
|
||||
{
|
||||
createdObjectCollectionWrapper.Add(newValue);
|
||||
IList createdObjectCollectionWrapper = (propertyArrayContract.ShouldCreateWrapper) ? propertyArrayContract.CreateWrapper(createdObjectCollection) : (IList)createdObjectCollection;
|
||||
IList newValues = (propertyArrayContract.ShouldCreateWrapper) ? propertyArrayContract.CreateWrapper(value) : (IList)value;
|
||||
|
||||
foreach (object newValue in newValues)
|
||||
{
|
||||
createdObjectCollectionWrapper.Add(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2048,25 +2051,28 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)propertyContract;
|
||||
|
||||
object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
|
||||
if (createdObjectDictionary != null)
|
||||
if (!dictionaryContract.IsReadOnlyOrFixedSize)
|
||||
{
|
||||
IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary;
|
||||
IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary)value;
|
||||
object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
|
||||
if (createdObjectDictionary != null)
|
||||
{
|
||||
IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary;
|
||||
IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary)value;
|
||||
|
||||
// Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
|
||||
IDictionaryEnumerator e = newValues.GetEnumerator();
|
||||
try
|
||||
{
|
||||
while (e.MoveNext())
|
||||
// Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
|
||||
IDictionaryEnumerator e = newValues.GetEnumerator();
|
||||
try
|
||||
{
|
||||
DictionaryEntry entry = e.Entry;
|
||||
targetDictionary[entry.Key] = entry.Value;
|
||||
while (e.MoveNext())
|
||||
{
|
||||
DictionaryEntry entry = e.Entry;
|
||||
targetDictionary[entry.Key] = entry.Value;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
(e as IDisposable)?.Dispose();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
(e as IDisposable)?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user