-Added JsonConstructorAttribute to explicitly define which constructor to use during deserialization
-Added IFormattable to JValue -Changed JValue ToString to call ToString on the internal value -Fixed code emit error when deserializing interfaces in certain situations
This commit is contained in:
@@ -7,6 +7,7 @@ using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Linq
|
||||
{
|
||||
@@ -106,6 +107,56 @@ namespace Newtonsoft.Json.Tests.Linq
|
||||
Assert.AreEqual("blah blah", (string)v);
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void JValueEquals()
|
||||
//{
|
||||
// JObject o = new JObject(
|
||||
// new JProperty("Null", new JValue(null, JTokenType.Null)),
|
||||
// new JProperty("Integer", new JValue(1)),
|
||||
// new JProperty("Float", new JValue(1.1)),
|
||||
// new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))),
|
||||
// new JProperty("Boolean", new JValue(true)),
|
||||
// new JProperty("String", new JValue("A string lol!")),
|
||||
// new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!")))
|
||||
// );
|
||||
|
||||
// dynamic d = o;
|
||||
|
||||
// Assert.IsTrue(d.Null == null);
|
||||
// Assert.IsTrue(d.Null == new JValue(null, JTokenType.Null));
|
||||
|
||||
// //if (d.NullValue == null)
|
||||
// // Console.WriteLine("Null");
|
||||
// //else
|
||||
// // Console.WriteLine("Not null");
|
||||
|
||||
// //Console.WriteLine(d.IntValue == 1);
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void JValueToString()
|
||||
{
|
||||
JObject o = new JObject(
|
||||
new JProperty("Null", new JValue(null, JTokenType.Null)),
|
||||
new JProperty("Integer", new JValue(1)),
|
||||
new JProperty("Float", new JValue(1.1)),
|
||||
new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))),
|
||||
new JProperty("Boolean", new JValue(true)),
|
||||
new JProperty("String", new JValue("A string lol!")),
|
||||
new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!")))
|
||||
);
|
||||
|
||||
dynamic d = o;
|
||||
|
||||
Assert.AreEqual("", d.Null.ToString());
|
||||
Assert.AreEqual("1", d.Integer.ToString());
|
||||
Assert.AreEqual("1.1", d.Float.ToString());
|
||||
Assert.AreEqual("12/29/2000 23:51:10", d.DateTime.ToString(null, CultureInfo.InvariantCulture));
|
||||
Assert.AreEqual("True", d.Boolean.ToString());
|
||||
Assert.AreEqual("A string lol!", d.String.ToString());
|
||||
Assert.AreEqual("System.Byte[]", d.Bytes.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JObjectGetDynamicPropertyNames()
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Linq
|
||||
{
|
||||
@@ -92,6 +93,30 @@ namespace Newtonsoft.Json.Tests.Linq
|
||||
Assert.AreEqual(JTokenType.String, stringValue.Type);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToString()
|
||||
{
|
||||
JValue v;
|
||||
|
||||
v = new JValue(true);
|
||||
Assert.AreEqual("True", v.ToString());
|
||||
|
||||
v = new JValue(Encoding.UTF8.GetBytes("Blah"));
|
||||
Assert.AreEqual("System.Byte[]", v.ToString(null, CultureInfo.InvariantCulture));
|
||||
|
||||
v = new JValue("I am a string!");
|
||||
Assert.AreEqual("I am a string!", v.ToString());
|
||||
|
||||
v = new JValue(null, JTokenType.Null);
|
||||
Assert.AreEqual("", v.ToString());
|
||||
|
||||
v = new JValue(null, JTokenType.Null);
|
||||
Assert.AreEqual("", v.ToString(null, CultureInfo.InvariantCulture));
|
||||
|
||||
v = new JValue(new DateTime(2000, 12, 12, 20, 59, 59, DateTimeKind.Utc), JTokenType.Date);
|
||||
Assert.AreEqual("12/12/2000 20:59:59", v.ToString(null, CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Cannot access child value on Newtonsoft.Json.Linq.JValue.")]
|
||||
public void Last()
|
||||
|
||||
@@ -287,7 +287,7 @@ keyword such as type of business.""
|
||||
Assert.AreEqual(@"""Width"": 1.1", o.Property("Width").ToString());
|
||||
Assert.AreEqual(@"1.1", o.Property("Width").Value.ToString());
|
||||
Assert.AreEqual(@"""Open"": false", o.Property("Open").ToString());
|
||||
Assert.AreEqual(@"false", o.Property("Open").Value.ToString());
|
||||
Assert.AreEqual(@"False", o.Property("Open").Value.ToString());
|
||||
|
||||
json = @"[null,undefined]";
|
||||
|
||||
@@ -296,8 +296,8 @@ keyword such as type of business.""
|
||||
null,
|
||||
undefined
|
||||
]", a.ToString());
|
||||
Assert.AreEqual(@"null", a.Children().ElementAt(0).ToString());
|
||||
Assert.AreEqual(@"undefined", a.Children().ElementAt(1).ToString());
|
||||
Assert.AreEqual(@"", a.Children().ElementAt(0).ToString());
|
||||
Assert.AreEqual(@"", a.Children().ElementAt(1).ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
public class ConstructorHandlingTests : TestFixtureBase
|
||||
{
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.PrivateConstructorTestClass. A class should either have a default constructor or only one constructor with arguments.")]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.PrivateConstructorTestClass. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.")]
|
||||
public void FailWithPrivateConstructorAndDefault()
|
||||
{
|
||||
string json = @"{Name:""Name!""}";
|
||||
|
||||
@@ -39,8 +39,58 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
public string AuthorCountry { get; set; }
|
||||
}
|
||||
|
||||
public interface IPerson
|
||||
{
|
||||
string FirstName { get; set; }
|
||||
string LastName { get; set; }
|
||||
DateTime BirthDate { get; set; }
|
||||
}
|
||||
|
||||
public class Employee : IPerson
|
||||
{
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public DateTime BirthDate { get; set; }
|
||||
|
||||
public string Department { get; set; }
|
||||
public string JobTitle { get; set; }
|
||||
}
|
||||
|
||||
public class IPersonContractResolver : DefaultContractResolver
|
||||
{
|
||||
protected override JsonContract CreateContract(Type objectType)
|
||||
{
|
||||
if (objectType == typeof(Employee))
|
||||
objectType = typeof(IPerson);
|
||||
|
||||
return base.CreateContract(objectType);
|
||||
}
|
||||
}
|
||||
|
||||
public class ContractResolverTests : TestFixtureBase
|
||||
{
|
||||
[Test]
|
||||
public void SerializeInterface()
|
||||
{
|
||||
Employee employee = new Employee
|
||||
{
|
||||
BirthDate = new DateTime(1977, 12, 30, 1, 1, 1, DateTimeKind.Utc),
|
||||
FirstName = "Maurice",
|
||||
LastName = "Moss",
|
||||
Department = "IT",
|
||||
JobTitle = "Support"
|
||||
};
|
||||
|
||||
string iPersonJson = JsonConvert.SerializeObject(employee, Formatting.Indented,
|
||||
new JsonSerializerSettings { ContractResolver = new IPersonContractResolver() });
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""FirstName"": ""Maurice"",
|
||||
""LastName"": ""Moss"",
|
||||
""BirthDate"": ""\/Date(252291661000)\/""
|
||||
}", iPersonJson);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SingleTypeWithMultipleContractResolvers()
|
||||
{
|
||||
@@ -127,4 +177,4 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
}", includeCompilerGeneratedJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1802,7 +1802,7 @@ keyword such as type of business.""
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.Event. A class should either have a default constructor or only one constructor with arguments.")]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.Event. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.")]
|
||||
public void FailWhenClassWithNoDefaultConstructorHasMultipleConstructorsWithArguments()
|
||||
{
|
||||
string json = @"{""sublocation"":""AlertEmailSender.Program.Main"",""userId"":0,""type"":0,""summary"":""Loading settings variables"",""details"":null,""stackTrace"":"" at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)\r\n at System.Environment.get_StackTrace()\r\n at mr.Logging.Event..ctor(String summary) in C:\\Projects\\MRUtils\\Logging\\Event.vb:line 71\r\n at AlertEmailSender.Program.Main(String[] args) in C:\\Projects\\AlertEmailSender\\AlertEmailSender\\Program.cs:line 25"",""tag"":null,""time"":""\/Date(1249591032026-0400)\/""}";
|
||||
@@ -4043,5 +4043,86 @@ keyword such as type of business.""
|
||||
|
||||
Assert.AreEqual(decimal.MinValue, obj.Value);
|
||||
}
|
||||
|
||||
public class NonPublicConstructorWithJsonConstructor
|
||||
{
|
||||
public string Value { get; private set; }
|
||||
public string Constructor { get; private set; }
|
||||
|
||||
[JsonConstructor]
|
||||
private NonPublicConstructorWithJsonConstructor()
|
||||
{
|
||||
Constructor = "NonPublic";
|
||||
}
|
||||
|
||||
public NonPublicConstructorWithJsonConstructor(string value)
|
||||
{
|
||||
Value = value;
|
||||
Constructor = "Public Paramatized";
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NonPublicConstructorWithJsonConstructorTest()
|
||||
{
|
||||
NonPublicConstructorWithJsonConstructor c = JsonConvert.DeserializeObject<NonPublicConstructorWithJsonConstructor>("{}");
|
||||
Assert.AreEqual("NonPublic", c.Constructor);
|
||||
}
|
||||
|
||||
public class PublicConstructorOverridenByJsonConstructor
|
||||
{
|
||||
public string Value { get; private set; }
|
||||
public string Constructor { get; private set; }
|
||||
|
||||
public PublicConstructorOverridenByJsonConstructor()
|
||||
{
|
||||
Constructor = "NonPublic";
|
||||
}
|
||||
|
||||
[JsonConstructor]
|
||||
public PublicConstructorOverridenByJsonConstructor(string value)
|
||||
{
|
||||
Value = value;
|
||||
Constructor = "Public Paramatized";
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PublicConstructorOverridenByJsonConstructorTest()
|
||||
{
|
||||
PublicConstructorOverridenByJsonConstructor c = JsonConvert.DeserializeObject<PublicConstructorOverridenByJsonConstructor>("{Value:'value!'}");
|
||||
Assert.AreEqual("Public Paramatized", c.Constructor);
|
||||
Assert.AreEqual("value!", c.Value);
|
||||
}
|
||||
|
||||
public class MultipleParamatrizedConstructorsJsonConstructor
|
||||
{
|
||||
public string Value { get; private set; }
|
||||
public int Age { get; private set; }
|
||||
public string Constructor { get; private set; }
|
||||
|
||||
public MultipleParamatrizedConstructorsJsonConstructor(string value)
|
||||
{
|
||||
Value = value;
|
||||
Constructor = "Public Paramatized 1";
|
||||
}
|
||||
|
||||
[JsonConstructor]
|
||||
public MultipleParamatrizedConstructorsJsonConstructor(string value, int age)
|
||||
{
|
||||
Value = value;
|
||||
Age = age;
|
||||
Constructor = "Public Paramatized 2";
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleParamatrizedConstructorsJsonConstructorTest()
|
||||
{
|
||||
MultipleParamatrizedConstructorsJsonConstructor c = JsonConvert.DeserializeObject<MultipleParamatrizedConstructorsJsonConstructor>("{Value:'value!', Age:1}");
|
||||
Assert.AreEqual("Public Paramatized 2", c.Constructor);
|
||||
Assert.AreEqual("value!", c.Value);
|
||||
Assert.AreEqual(1, c.Age);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Instructs the <see cref="JsonSerializer"/> not to serialize the public field or public read/write property value.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public sealed class JsonConstructorAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ using Newtonsoft.Json.Schema;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
@@ -300,8 +301,11 @@ namespace Newtonsoft.Json
|
||||
|
||||
if (schema.Enum != null)
|
||||
{
|
||||
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
|
||||
value.WriteTo(new JsonTextWriter(sw));
|
||||
|
||||
if (!schema.Enum.ContainsValue(value, new JTokenEqualityComparer()))
|
||||
RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, value),
|
||||
RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, sw.ToString()),
|
||||
schema);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Newtonsoft.Json.Linq
|
||||
/// <summary>
|
||||
/// Represents a value in JSON (string, integer, date, etc).
|
||||
/// </summary>
|
||||
public class JValue : JToken, IEquatable<JValue>
|
||||
public class JValue : JToken, IEquatable<JValue>, IFormattable
|
||||
{
|
||||
private JTokenType _valueType;
|
||||
private object _value;
|
||||
@@ -406,6 +406,40 @@ namespace Newtonsoft.Json.Linq
|
||||
return _value.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (_value == null)
|
||||
return string.Empty;
|
||||
|
||||
return _value.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <param name="formatProvider">The format provider.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> that represents this instance.
|
||||
/// </returns>
|
||||
public string ToString(string format, IFormatProvider formatProvider)
|
||||
{
|
||||
if (_value == null)
|
||||
return string.Empty;
|
||||
|
||||
IFormattable formattable = _value as IFormattable;
|
||||
if (formattable != null)
|
||||
return formattable.ToString(format, formatProvider);
|
||||
else
|
||||
return _value.ToString();
|
||||
}
|
||||
|
||||
#if !(NET35 || NET20 || WINDOWS_PHONE)
|
||||
/// <summary>
|
||||
/// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
|
||||
@@ -440,6 +474,26 @@ namespace Newtonsoft.Json.Linq
|
||||
result = ConvertUtils.Convert(instance.Value, CultureInfo.InvariantCulture, binder.Type);
|
||||
return true;
|
||||
}
|
||||
|
||||
//public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, out object result)
|
||||
//{
|
||||
// dynamic d1 = arg;
|
||||
// dynamic d2 = instance._value;
|
||||
// //// use built in JValue equals
|
||||
// //if (arg is JValue)
|
||||
// //{
|
||||
// // result = null;
|
||||
// // return false;
|
||||
// //}
|
||||
|
||||
// //if (binder.Operation == ExpressionType.Equal)
|
||||
// //{
|
||||
// // result = Compare(instance.Type, instance.Value, arg);
|
||||
// // return true;
|
||||
// //}
|
||||
|
||||
// //return base.TryBinaryOperation(instance, binder, arg, out result);
|
||||
//}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
<Compile Include="Converters\KeyValuePairConverter.cs" />
|
||||
<Compile Include="Converters\RegexConverter.cs" />
|
||||
<Compile Include="Converters\StringEnumConverter.cs" />
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
|
||||
<Compile Include="Linq\JPath.cs" />
|
||||
<Compile Include="Linq\JRaw.cs" />
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
<Compile Include="Converters\RegexConverter.cs" />
|
||||
<Compile Include="Converters\StringEnumConverter.cs" />
|
||||
<Compile Include="ConstructorHandling.cs" />
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="Utilities\DynamicProxy.cs" />
|
||||
<Compile Include="Linq\JPath.cs" />
|
||||
<Compile Include="Linq\JRaw.cs" />
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
<Compile Include="DefaultValueHandling.cs" />
|
||||
<Compile Include="IJsonLineInfo.cs" />
|
||||
<Compile Include="JsonArrayAttribute.cs" />
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="JsonContainerAttribute.cs" />
|
||||
<Compile Include="JsonConvert.cs" />
|
||||
<Compile Include="JsonConverter.cs" />
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<Compile Include="DefaultValueHandling.cs" />
|
||||
<Compile Include="IJsonLineInfo.cs" />
|
||||
<Compile Include="JsonArrayAttribute.cs" />
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="JsonContainerAttribute.cs" />
|
||||
<Compile Include="JsonConvert.cs" />
|
||||
<Compile Include="JsonConverter.cs" />
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
<Compile Include="Converters\RegexConverter.cs" />
|
||||
<Compile Include="Converters\StringEnumConverter.cs" />
|
||||
<Compile Include="ConstructorHandling.cs" />
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="Utilities\DynamicProxy.cs" />
|
||||
<Compile Include="Linq\JPath.cs" />
|
||||
<Compile Include="Linq\JRaw.cs" />
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (!(obj is ResolverContractKey))
|
||||
return false;
|
||||
|
||||
return Equals((ResolverContractKey) obj);
|
||||
return Equals((ResolverContractKey)obj);
|
||||
}
|
||||
|
||||
public bool Equals(ResolverContractKey other)
|
||||
@@ -277,17 +277,31 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType);
|
||||
contract.Properties.AddRange(CreateProperties(contract.UnderlyingType, contract.MemberSerialization));
|
||||
if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
|
||||
if (objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(c => c.IsDefined(typeof(JsonConstructorAttribute), true)))
|
||||
contract.OverrideConstructor = GetAttributeConstructor(objectType);
|
||||
else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
|
||||
contract.ParametrizedConstructor = GetParametrizedConstructor(objectType);
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
private ConstructorInfo GetAttributeConstructor(Type objectType)
|
||||
{
|
||||
IList<ConstructorInfo> markedConstructors = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(c => c.IsDefined(typeof(JsonConstructorAttribute), true)).ToList();
|
||||
|
||||
if (markedConstructors.Count > 1)
|
||||
throw new Exception("Multiple constructors with the JsonConstructorAttribute.");
|
||||
else if (markedConstructors.Count == 1)
|
||||
return markedConstructors[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ConstructorInfo GetParametrizedConstructor(Type objectType)
|
||||
{
|
||||
ConstructorInfo[] constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
|
||||
IList<ConstructorInfo> constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
if (constructors.Length == 1)
|
||||
if (constructors.Count == 1)
|
||||
return constructors[0];
|
||||
else
|
||||
return null;
|
||||
@@ -309,7 +323,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
|
||||
#if !PocketPC && !NET20
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")]
|
||||
#endif
|
||||
private void InitializeContract(JsonContract contract)
|
||||
{
|
||||
@@ -412,7 +426,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
JsonPrimitiveContract contract = new JsonPrimitiveContract(objectType);
|
||||
InitializeContract(contract);
|
||||
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
@@ -440,7 +454,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
JsonISerializableContract contract = new JsonISerializableContract(objectType);
|
||||
InitializeContract(contract);
|
||||
|
||||
ConstructorInfo constructorInfo = objectType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new [] {typeof (SerializationInfo), typeof (StreamingContext)}, null);
|
||||
ConstructorInfo constructorInfo = objectType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(SerializationInfo), typeof(StreamingContext) }, null);
|
||||
if (constructorInfo != null)
|
||||
{
|
||||
MethodCall<object, object> methodCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(constructorInfo);
|
||||
@@ -574,7 +588,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (attributeType == typeof(OnErrorAttribute))
|
||||
{
|
||||
if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext))
|
||||
throw new Exception("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof (StreamingContext), typeof(ErrorContext)));
|
||||
throw new Exception("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), typeof(ErrorContext)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -646,7 +660,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
JsonProperty property = new JsonProperty();
|
||||
property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member);
|
||||
property.ValueProvider = CreateMemberValueProvider(member);
|
||||
|
||||
|
||||
// resolve converter for property
|
||||
// the class type might have a converter but the property converter takes presidence
|
||||
property.Converter = JsonTypeReflector.GetJsonConverter(member, property.PropertyType);
|
||||
@@ -689,7 +703,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
(memberSerialization == MemberSerialization.OptIn
|
||||
&& propertyAttribute == null
|
||||
#if !PocketPC && !NET20
|
||||
&& dataMemberAttribute == null
|
||||
&& dataMemberAttribute == null
|
||||
#endif
|
||||
));
|
||||
|
||||
@@ -735,7 +749,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
MethodCall<object, object> shouldSerializeCall =
|
||||
JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(shouldSerializeMethod);
|
||||
|
||||
return o => (bool) shouldSerializeCall(o);
|
||||
return o => (bool)shouldSerializeCall(o);
|
||||
}
|
||||
|
||||
private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member)
|
||||
|
||||
@@ -45,6 +45,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <value>The object's properties.</value>
|
||||
public JsonPropertyCollection Properties { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the override constructor used to create the object.
|
||||
/// This is set when a constructor is marked up using the
|
||||
/// JsonConstructor attribute.
|
||||
/// </summary>
|
||||
/// <value>The override constructor.</value>
|
||||
public ConstructorInfo OverrideConstructor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parametrized constructor used to create the object.
|
||||
/// </summary>
|
||||
|
||||
@@ -831,27 +831,35 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (contract.UnderlyingType.IsInterface || contract.UnderlyingType.IsAbstract)
|
||||
throw new JsonSerializationException("Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
if (contract.DefaultCreator != null &&
|
||||
if (contract.OverrideConstructor != null)
|
||||
{
|
||||
if (contract.OverrideConstructor.GetParameters().Length > 0)
|
||||
return CreateObjectFromNonDefaultConstructor(reader, contract, contract.OverrideConstructor, id);
|
||||
|
||||
newObject = contract.OverrideConstructor.Invoke(null);
|
||||
}
|
||||
else if (contract.DefaultCreator != null &&
|
||||
(!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
|
||||
{
|
||||
newObject = contract.DefaultCreator();
|
||||
}
|
||||
|
||||
if (newObject != null)
|
||||
else if (contract.ParametrizedConstructor != null)
|
||||
{
|
||||
PopulateObject(newObject, reader, contract, id);
|
||||
return newObject;
|
||||
return CreateObjectFromNonDefaultConstructor(reader, contract, contract.ParametrizedConstructor, id);
|
||||
}
|
||||
|
||||
return CreateObjectFromNonDefaultConstructor(reader, contract, id);
|
||||
if (newObject == null)
|
||||
throw new JsonSerializationException("Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
PopulateObject(newObject, reader, contract, id);
|
||||
return newObject;
|
||||
}
|
||||
|
||||
private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, string id)
|
||||
private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, ConstructorInfo constructorInfo, string id)
|
||||
{
|
||||
Type objectType = contract.UnderlyingType;
|
||||
ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");
|
||||
|
||||
if (contract.ParametrizedConstructor == null)
|
||||
throw new JsonSerializationException("Unable to find a constructor to use for type {0}. A class should either have a default constructor or only one constructor with arguments.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
Type objectType = contract.UnderlyingType;
|
||||
|
||||
// create a dictionary to put retrieved values into
|
||||
IDictionary<JsonProperty, object> propertyValues = contract.Properties.Where(p => !p.Ignored).ToDictionary(kv => kv, kv => (object)null);
|
||||
@@ -897,7 +905,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
} while (!exit && reader.Read());
|
||||
|
||||
IDictionary<ParameterInfo, object> constructorParameters = contract.ParametrizedConstructor.GetParameters().ToDictionary(p => p, p => (object)null);
|
||||
IDictionary<ParameterInfo, object> constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object)null);
|
||||
IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();
|
||||
|
||||
foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues)
|
||||
@@ -909,7 +917,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
remainingPropertyValues.Add(propertyValue);
|
||||
}
|
||||
|
||||
object createdObject = contract.ParametrizedConstructor.Invoke(constructorParameters.Values.ToArray());
|
||||
object createdObject = constructorInfo.Invoke(constructorParameters.Values.ToArray());
|
||||
|
||||
if (id != null)
|
||||
Serializer.ReferenceResolver.AddReference(id, createdObject);
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
DynamicMethod dynamicMethod = !owner.IsInterface
|
||||
? new DynamicMethod(name, returnType, parameterTypes, owner, true)
|
||||
: new DynamicMethod(name, returnType, parameterTypes, (Module)null, true);
|
||||
: new DynamicMethod(name, returnType, parameterTypes, owner.Module, true);
|
||||
|
||||
return dynamicMethod;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user