-Changed serializer to create objects using GetUninitializedObject when deserializing fields

This commit is contained in:
James Newton-King
2012-07-10 22:57:27 +12:00
parent 9d7046bca2
commit cfb2499a35
5 changed files with 97 additions and 4 deletions
@@ -72,5 +72,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.5.7.15030")]
[assembly: AssemblyFileVersion("4.5.7.15110")]
#endif
@@ -6523,6 +6523,73 @@ Parameter name: value",
""value"": ""test value""
}", json);
}
[JsonObject(MemberSerialization.Fields)]
public class MyTuple<T1>
{
private readonly T1 m_Item1;
public MyTuple(T1 item1)
{
m_Item1 = item1;
}
public T1 Item1
{
get { return m_Item1; }
}
}
[Test]
public void SerializeCustomTupleWithSerializableAttribute()
{
var tuple = new MyTuple<int>(500);
var json = JsonConvert.SerializeObject(tuple);
Assert.AreEqual(@"{""m_Item1"":500}", json);
MyTuple<int> obj = null;
Action doStuff = () =>
{
obj = JsonConvert.DeserializeObject<MyTuple<int>>(json);
};
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
doStuff();
Assert.AreEqual(500, obj.Item1);
#else
ExceptionAssert.Throws<JsonSerializationException>(
"Unable to find a constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+MyTuple`1[System.Int32]. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'm_Item1', line 1, position 11.",
doStuff);
#endif
}
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE || NET35 || NET20)
[Test]
public void SerializeTupleWithSerializableAttribute()
{
var tuple = Tuple.Create(500);
var json = JsonConvert.SerializeObject(tuple, new JsonSerializerSettings
{
ContractResolver = new SerializableContractResolver()
});
Assert.AreEqual(@"{""m_Item1"":500}", json);
var obj = JsonConvert.DeserializeObject<Tuple<int>>(json, new JsonSerializerSettings
{
ContractResolver = new SerializableContractResolver()
});
Assert.AreEqual(500, obj.Item1);
}
public class SerializableContractResolver : DefaultContractResolver
{
public SerializableContractResolver()
{
IgnoreSerializableAttribute = false;
}
}
#endif
}
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
@@ -90,7 +90,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.5.7.15030")]
[assembly: AssemblyFileVersion("4.5.7.15110")]
#endif
[assembly: CLSCompliant(true)]
@@ -372,6 +372,13 @@ namespace Newtonsoft.Json.Serialization
contract.ConstructorParameters.AddRange(CreateConstructorParameters(constructor, contract.Properties));
}
}
else if (contract.MemberSerialization == MemberSerialization.Fields)
{
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
// mimic DataContractSerializer behaviour and create uninitialized object when populating fields
contract.DefaultCreator = contract.GetUninitializedObject;
#endif
}
else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
{
ConstructorInfo constructor = GetParametrizedConstructor(contract.NonNullableUnderlyingType);
@@ -899,8 +906,17 @@ namespace Newtonsoft.Json.Serialization
bool hasExplicitAttribute;
SetPropertySettingsFromAttributes(property, member.GetCustomAttributeProvider(), member.Name, member.DeclaringType, memberSerialization, out allowNonPublicAccess, out hasExplicitAttribute);
property.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess);
property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, hasExplicitAttribute);
if (memberSerialization != MemberSerialization.Fields)
{
property.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess);
property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, hasExplicitAttribute);
}
else
{
// write to readonly fields
property.Readable = true;
property.Writable = true;
}
property.ShouldSerialize = CreateShouldSerializeTest(member);
SetIsSpecifiedActions(property, member, allowNonPublicAccess);
@@ -25,6 +25,8 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security;
namespace Newtonsoft.Json.Serialization
{
@@ -114,5 +116,13 @@ namespace Newtonsoft.Json.Serialization
Properties = new JsonPropertyCollection(UnderlyingType);
ConstructorParameters = new JsonPropertyCollection(UnderlyingType);
}
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
[SecuritySafeCritical]
internal object GetUninitializedObject()
{
return FormatterServices.GetUninitializedObject(NonNullableUnderlyingType);
}
#endif
}
}