-Fixed incorrect check when looking for non-default constructors on collections
This commit is contained in:
@@ -1917,6 +1917,86 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
Assert.AreEqual(deserializeTest2["testkey"], "");
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void DeserializeCollectionWithConstructorArrayArgument()
|
||||
{
|
||||
var v = new ReadOnlyCollectionWithArrayArgument<double>(new[] { -0.014147478859765236, -0.011419606805541858, -0.010038461483676238 });
|
||||
var json = JsonConvert.SerializeObject(v);
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(() =>
|
||||
{
|
||||
JsonConvert.DeserializeObject<ReadOnlyCollectionWithArrayArgument<double>>(json);
|
||||
}, "Unable to find a constructor to use for type Newtonsoft.Json.Tests.Serialization.ReadOnlyCollectionWithArrayArgument`1[System.Double]. Path '', line 1, position 1.");
|
||||
}
|
||||
}
|
||||
|
||||
public class ReadOnlyCollectionWithArrayArgument<T> : IList<T>
|
||||
{
|
||||
private readonly IList<T> _values;
|
||||
|
||||
public ReadOnlyCollectionWithArrayArgument(T[] args)
|
||||
{
|
||||
_values = args ?? (IList<T>)new List<T>();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return _values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _values.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int Count { get; }
|
||||
public bool IsReadOnly { get; }
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
set { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
|
||||
@@ -489,6 +489,8 @@ namespace Newtonsoft.Json.Linq
|
||||
internal override void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments)
|
||||
{
|
||||
JTokenReader tokenReader = reader as JTokenReader;
|
||||
|
||||
// closing the token wrather than reading then writing it doesn't lose some type information, e.g. Guid, byte[], etc
|
||||
if (tokenReader != null && writeChildren && writeDateConstructorAsDate && writeComments)
|
||||
{
|
||||
if (tokenReader.TokenType == JsonToken.None)
|
||||
|
||||
@@ -172,7 +172,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (keyType != null && valueType != null)
|
||||
{
|
||||
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType));
|
||||
_parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(
|
||||
CreatedType,
|
||||
typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType),
|
||||
typeof(IDictionary<,>).MakeGenericType(keyType, valueType));
|
||||
|
||||
#if !(NET35 || NET20)
|
||||
if (!HasParameterizedCreatorInternal && underlyingType.Name == FSharpUtils.FSharpMapTypeName)
|
||||
|
||||
@@ -113,6 +113,13 @@ namespace Newtonsoft.Json.Utilities
|
||||
}
|
||||
|
||||
public static ConstructorInfo ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType)
|
||||
{
|
||||
Type genericConstructorArgument = typeof(IList<>).MakeGenericType(collectionItemType);
|
||||
|
||||
return ResolveEnumerableCollectionConstructor(collectionType, collectionItemType, genericConstructorArgument);
|
||||
}
|
||||
|
||||
public static ConstructorInfo ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType, Type constructorArgumentType)
|
||||
{
|
||||
Type genericEnumerable = typeof(IEnumerable<>).MakeGenericType(collectionItemType);
|
||||
ConstructorInfo match = null;
|
||||
@@ -123,7 +130,9 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
if (genericEnumerable == parameters[0].ParameterType)
|
||||
Type parameterType = parameters[0].ParameterType;
|
||||
|
||||
if (genericEnumerable == parameterType)
|
||||
{
|
||||
// exact match
|
||||
match = constructor;
|
||||
@@ -133,7 +142,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
// incase we can't find an exact match, use first inexact
|
||||
if (match == null)
|
||||
{
|
||||
if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
|
||||
if (parameterType.IsAssignableFrom(constructorArgumentType))
|
||||
{
|
||||
match = constructor;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user