This commit is contained in:
Lucas Loegel
2019-03-30 17:01:39 +13:00
committed by James Newton-King
parent 5712e024b2
commit 05d721e36f
3 changed files with 86 additions and 21 deletions
@@ -0,0 +1,64 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !(NET20 || NET35 || NET40)
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
#if DNXCORE50
using Xunit;
using Test = Xunit.FactAttribute;
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
#else
using NUnit.Framework;
#endif
namespace Newtonsoft.Json.Tests.Issues
{
public class Issue1984
{
[Test]
public void Test_NullValue()
{
var actual = JsonConvert.DeserializeObject<A>("{ Values: null}");
Assert.IsNotNull(actual);
Assert.IsNull(actual.Values);
}
[Test]
public void Test_WithoutValue()
{
var actual = JsonConvert.DeserializeObject<A>("{ }");
Assert.IsNotNull(actual);
Assert.IsNull(actual.Values);
}
public class A
{
public ImmutableArray<string>? Values { get; set; }
}
}
}
#endif
@@ -1216,7 +1216,7 @@ namespace Newtonsoft.Json.Serialization
if (typeof(IEnumerable).IsAssignableFrom(t))
{
return CreateArrayContract(t);
return CreateArrayContract(objectType);
}
if (CanConvertToString(t))
@@ -115,6 +115,7 @@ namespace Newtonsoft.Json.Serialization
public JsonArrayContract(Type underlyingType)
: base(underlyingType)
{
var t = ReflectionUtils.EnsureNotByRefType(ReflectionUtils.EnsureNotNullableType(underlyingType));
ContractType = JsonContractType.Array;
IsArray = CreatedType.IsArray;
@@ -130,58 +131,58 @@ namespace Newtonsoft.Json.Serialization
canDeserialize = true;
IsMultidimensionalArray = (IsArray && UnderlyingType.GetArrayRank() > 1);
}
else if (typeof(IList).IsAssignableFrom(underlyingType))
else if (typeof(IList).IsAssignableFrom(t))
{
if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(ICollection<>), out _genericCollectionDefinitionType))
{
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
}
else
{
CollectionItemType = ReflectionUtils.GetCollectionItemType(underlyingType);
CollectionItemType = ReflectionUtils.GetCollectionItemType(t);
}
if (underlyingType == typeof(IList))
if (t == typeof(IList))
{
CreatedType = typeof(List<object>);
}
if (CollectionItemType != null)
{
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType);
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(t, CollectionItemType);
}
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>));
IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(t, typeof(ReadOnlyCollection<>));
canDeserialize = true;
}
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
else if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(ICollection<>), out _genericCollectionDefinitionType))
{
CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(ICollection<>))
|| ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IList<>)))
if (ReflectionUtils.IsGenericDefinition(t, typeof(ICollection<>))
|| ReflectionUtils.IsGenericDefinition(t, typeof(IList<>)))
{
CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
}
#if HAVE_ISET
if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(ISet<>)))
if (ReflectionUtils.IsGenericDefinition(t, typeof(ISet<>)))
{
CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType);
}
#endif
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType);
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(t, CollectionItemType);
canDeserialize = true;
ShouldCreateWrapper = true;
}
#if HAVE_READ_ONLY_COLLECTIONS
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IReadOnlyCollection<>), out tempCollectionType))
else if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IReadOnlyCollection<>), out tempCollectionType))
{
CollectionItemType = tempCollectionType.GetGenericArguments()[0];
if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IReadOnlyCollection<>))
|| ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IReadOnlyList<>)))
if (ReflectionUtils.IsGenericDefinition(t, typeof(IReadOnlyCollection<>))
|| ReflectionUtils.IsGenericDefinition(t, typeof(IReadOnlyList<>)))
{
CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType);
}
@@ -190,14 +191,14 @@ namespace Newtonsoft.Json.Serialization
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, CollectionItemType);
#if HAVE_FSHARP_TYPES
StoreFSharpListCreatorIfNecessary(underlyingType);
StoreFSharpListCreatorIfNecessary(t);
#endif
IsReadOnlyOrFixedSize = true;
canDeserialize = HasParameterizedCreatorInternal;
}
#endif
else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IEnumerable<>), out tempCollectionType))
else if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IEnumerable<>), out tempCollectionType))
{
CollectionItemType = tempCollectionType.GetGenericArguments()[0];
@@ -206,13 +207,13 @@ namespace Newtonsoft.Json.Serialization
CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
}
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(underlyingType, CollectionItemType);
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(t, CollectionItemType);
#if HAVE_FSHARP_TYPES
StoreFSharpListCreatorIfNecessary(underlyingType);
StoreFSharpListCreatorIfNecessary(t);
#endif
if (underlyingType.IsGenericType() && underlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
if (t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
_genericCollectionDefinitionType = tempCollectionType;
@@ -252,7 +253,7 @@ namespace Newtonsoft.Json.Serialization
#endif
if (ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(
underlyingType,
t,
CollectionItemType,
out Type immutableCreatedType,
out ObjectConstructor<object> immutableParameterizedCreator))