-Added ObjectCreationHandling to JsonPropertyAttribute
-Added IValueProvider, ReflectionValueProvider, DynamicValueProvider -Added Dynamic.snk -Added Required enum with options Default, AllowNull and Always -Added serialization event support to Silverlight version -Added Converter to JsonProperty for JsonConverter -Changed IsRequired to Required enum -Changed schema generator to allow for Required enum options -Changed Silverlight project version to Silverlight 3 -Improved error message when JSON array encountered for object and vice-versa when deserializing -Improved error message for converting types when deserializing -Improved error message from getting and setting properties when serializing and deserializing -Fixed empty string being converted to null when deserializing -Removed dependency on Entity Framework and LINQ to SQL assemblies
This commit is contained in:
@@ -60,7 +60,12 @@
|
||||
JSON array populated with the IEnumerable values. Placing the JsonPropertyAttribute overrides this
|
||||
behavor and forces the serializer to serialize the class's fields and properties.</p>
|
||||
<h5>JsonPropertyAttribute</h5>
|
||||
<p>Allows the name of the serialized member to be customized. The attribute also indicates that a member should be serialized when member serialization is set to opt-in.</p>
|
||||
<p>JsonPropertyAttribute has a number of uses:</p>
|
||||
<ul>
|
||||
<li>By default the JSON property will have the same name as the .NET property. This attribute allows the name to be customized.</li>
|
||||
<li>Indicates that a property should be serialized when member serialization is set to opt-in.</li>
|
||||
<li>Includes non-public properties in serialization and deserialization.</li>
|
||||
</ul>
|
||||
<h5>JsonIgnoreAttribute</h5>
|
||||
<p>Excludes a field or property from serialization.</p>
|
||||
<h5>JsonConverterAttribute</h5>
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
<AssemblyName>Newtonsoft.Json.Tests.Silverlight</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<SilverlightApplication>false</SilverlightApplication>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -195,7 +200,7 @@
|
||||
<Name>Newtonsoft.Json.Silverlight</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\v3.0\Microsoft.Silverlight.CSharp.targets" Condition="" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -113,6 +113,12 @@
|
||||
<Compile Include="Linq\ComponentModel\JTypeDescriptorTests.cs" />
|
||||
<Compile Include="Linq\JPathTests.cs" />
|
||||
<Compile Include="Serialization\ConstructorHandlingTests.cs" />
|
||||
<Compile Include="Serialization\ContractResolverTests.cs" />
|
||||
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
|
||||
<Compile Include="Serialization\NullValueHandlingTests.cs" />
|
||||
<Compile Include="TestObjects\Car.cs" />
|
||||
<Compile Include="TestObjects\Computer.cs" />
|
||||
<Compile Include="TestObjects\Movie.cs" />
|
||||
<Compile Include="TestObjects\PersonError.cs" />
|
||||
<Compile Include="TestObjects\PrivateConstructorTestClass.cs" />
|
||||
<Compile Include="TestObjects\PrivateConstructorWithPublicParametizedConstructorTestClass.cs" />
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Newtonsoft.Json.Tests
|
||||
public class PerformanceTests : TestFixtureBase
|
||||
{
|
||||
private int Iterations = 100;
|
||||
//private int Iterations = 5000;
|
||||
|
||||
public enum SerializeMethod
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Newtonsoft.Json.Tests.Schema
|
||||
}
|
||||
}", json);
|
||||
}
|
||||
|
||||
|
||||
#if !PocketPC
|
||||
[Test]
|
||||
public void Generate_DefaultValueAttributeTestClass()
|
||||
@@ -179,7 +179,7 @@ namespace Newtonsoft.Json.Tests.Schema
|
||||
|
||||
Assert.AreEqual(JsonSchemaType.String, schema.Properties["FirstName"].Type);
|
||||
Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Null, schema.Properties["MiddleName"].Type);
|
||||
Assert.AreEqual(JsonSchemaType.String, schema.Properties["LastName"].Type);
|
||||
Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Null, schema.Properties["LastName"].Type);
|
||||
Assert.AreEqual(JsonSchemaType.String, schema.Properties["BirthDate"].Type);
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Newtonsoft.Json.Tests.Schema
|
||||
|
||||
JsonSchema schema = generator.Generate(typeof(CircularReferenceWithIdClass));
|
||||
|
||||
Assert.AreEqual(JsonSchemaType.String, schema.Properties["Name"].Type);
|
||||
Assert.AreEqual(JsonSchemaType.String | JsonSchemaType.Null, schema.Properties["Name"].Type);
|
||||
Assert.AreEqual("MyExplicitId", schema.Id);
|
||||
Assert.AreEqual(JsonSchemaType.Object, schema.Properties["Child"].Type);
|
||||
Assert.AreEqual(schema, schema.Properties["Child"]);
|
||||
@@ -287,7 +287,7 @@ namespace Newtonsoft.Json.Tests.Schema
|
||||
{
|
||||
IList<JsonProperty> properties = base.CreateProperties(contract);
|
||||
|
||||
JsonPropertyCollection c = new JsonPropertyCollection();
|
||||
JsonPropertyCollection c = new JsonPropertyCollection(contract);
|
||||
CollectionUtils.AddRange(c, (IEnumerable)properties.Where(m => m.PropertyName != "Root"));
|
||||
|
||||
return c;
|
||||
|
||||
+3
-1
@@ -116,7 +116,9 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
|
||||
Assert.AreEqual("Private!", ReflectionUtils.GetMemberValue(typeof(PrivateMembersClass).GetField("_privateString", BindingFlags.Instance | BindingFlags.NonPublic), deserializedPrivateMembersClass));
|
||||
Assert.AreEqual("Internal!", ReflectionUtils.GetMemberValue(typeof(PrivateMembersClass).GetField("_internalString", BindingFlags.Instance | BindingFlags.NonPublic), deserializedPrivateMembersClass));
|
||||
Assert.AreEqual(-2, ReflectionUtils.GetMemberValue(typeof(PrivateMembersClass).GetField("i", BindingFlags.Instance | BindingFlags.NonPublic), deserializedPrivateMembersClass));
|
||||
|
||||
// readonly
|
||||
Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(PrivateMembersClass).GetField("i", BindingFlags.Instance | BindingFlags.NonPublic), deserializedPrivateMembersClass));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Serialization
|
||||
{
|
||||
public class DynamicContractResolver : DefaultContractResolver
|
||||
{
|
||||
private readonly char _startingWithChar;
|
||||
public DynamicContractResolver(char startingWithChar)
|
||||
{
|
||||
_startingWithChar = startingWithChar;
|
||||
}
|
||||
|
||||
protected override IList<JsonProperty> CreateProperties(JsonObjectContract contract)
|
||||
{
|
||||
IList<JsonProperty> properties = base.CreateProperties(contract);
|
||||
|
||||
// only serializer properties that start with the specified character
|
||||
properties =
|
||||
properties.Where(p => p.PropertyName.StartsWith(_startingWithChar.ToString())).ToList();
|
||||
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
public class Book
|
||||
{
|
||||
public string BookName { get; set; }
|
||||
public decimal BookPrice { get; set; }
|
||||
public string AuthorName { get; set; }
|
||||
public int AuthorAge { get; set; }
|
||||
public string AuthorCountry { get; set; }
|
||||
}
|
||||
|
||||
public class ContractResolverTests : TestFixtureBase
|
||||
{
|
||||
[Test]
|
||||
public void SingleTypeWithMultipleContractResolvers()
|
||||
{
|
||||
Book book = new Book
|
||||
{
|
||||
BookName = "The Gathering Storm",
|
||||
BookPrice = 16.19m,
|
||||
AuthorName = "Brandon Sanderson",
|
||||
AuthorAge = 34,
|
||||
AuthorCountry = "United States of America"
|
||||
};
|
||||
|
||||
string startingWithA = JsonConvert.SerializeObject(book, Formatting.Indented,
|
||||
new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('A') });
|
||||
|
||||
// {
|
||||
// "AuthorName": "Brandon Sanderson",
|
||||
// "AuthorAge": 34,
|
||||
// "AuthorCountry": "United States of America"
|
||||
// }
|
||||
|
||||
string startingWithB = JsonConvert.SerializeObject(book, Formatting.Indented,
|
||||
new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('B') });
|
||||
|
||||
// {
|
||||
// "BookName": "The Gathering Storm",
|
||||
// "BookPrice": 16.19
|
||||
// }
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""AuthorName"": ""Brandon Sanderson"",
|
||||
""AuthorAge"": 34,
|
||||
""AuthorCountry"": ""United States of America""
|
||||
}", startingWithA);
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""BookName"": ""The Gathering Storm"",
|
||||
""BookPrice"": 16.19
|
||||
}", startingWithB);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Tests.TestObjects;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Serialization
|
||||
{
|
||||
public class DefaultValueHandlingTests : TestFixtureBase
|
||||
{
|
||||
[Test]
|
||||
public void SerializeInvoice()
|
||||
{
|
||||
Invoice invoice = new Invoice
|
||||
{
|
||||
Company = "Acme Ltd.",
|
||||
Amount = 50.0m,
|
||||
Paid = false,
|
||||
FollowUpDays = 30,
|
||||
FollowUpEmailAddress = string.Empty,
|
||||
PaidDate = null
|
||||
};
|
||||
|
||||
string included = JsonConvert.SerializeObject(invoice,
|
||||
Formatting.Indented,
|
||||
new JsonSerializerSettings { });
|
||||
|
||||
// {
|
||||
// "Company": "Acme Ltd.",
|
||||
// "Amount": 50.0,
|
||||
// "Paid": false,
|
||||
// "PaidDate": null,
|
||||
// "FollowUpDays": 30,
|
||||
// "FollowUpEmailAddress": ""
|
||||
// }
|
||||
|
||||
string ignored = JsonConvert.SerializeObject(invoice,
|
||||
Formatting.Indented,
|
||||
new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
|
||||
// {
|
||||
// "Company": "Acme Ltd.",
|
||||
// "Amount": 50.0
|
||||
// }
|
||||
|
||||
Console.WriteLine(included);
|
||||
Console.WriteLine(ignored);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultValueAttributeTest()
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass(),
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{""TestField1"":0,""TestProperty1"":null}", json);
|
||||
|
||||
json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass { TestField1 = int.MinValue, TestProperty1 = "NotDefault" },
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{""TestField1"":-2147483648,""TestProperty1"":""NotDefault""}", json);
|
||||
|
||||
json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass { TestField1 = 21, TestProperty1 = "NotDefault" },
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{""TestProperty1"":""NotDefault""}", json);
|
||||
|
||||
json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass { TestField1 = 21, TestProperty1 = "TestProperty1Value" },
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{}", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ using System.Runtime.Serialization.Json;
|
||||
using Newtonsoft.Json.Tests.TestObjects;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Serialization
|
||||
{
|
||||
@@ -60,6 +61,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
Store deserializedStore = (Store)JsonConvert.DeserializeObject(jsonText, typeof(Store));
|
||||
|
||||
Assert.AreEqual(store.Establised, deserializedStore.Establised);
|
||||
Assert.AreEqual(store.product.Count, deserializedStore.product.Count);
|
||||
|
||||
Console.WriteLine(jsonText);
|
||||
}
|
||||
@@ -509,31 +511,6 @@ keyword such as type of business.""
|
||||
CollectionAssert.AreEqual(collection, collectionNew);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NullValueHandlingSerialization()
|
||||
{
|
||||
Store s1 = new Store();
|
||||
|
||||
JsonSerializer jsonSerializer = new JsonSerializer();
|
||||
jsonSerializer.NullValueHandling = NullValueHandling.Ignore;
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
jsonSerializer.Serialize(sw, s1);
|
||||
|
||||
//JsonConvert.ConvertDateTimeToJavaScriptTicks(s1.Establised.DateTime)
|
||||
|
||||
Assert.AreEqual(@"{""Color"":4,""Establised"":""\/Date(1264122061000+0000)\/"",""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""ExpiryDate"":""\/Date(949532490000)\/"",""Price"":0.0},{""Name"":""Alien"",""ExpiryDate"":""\/Date(946684800000)\/"",""Price"":0.0}]}", sw.GetStringBuilder().ToString());
|
||||
|
||||
Store s2 = (Store)jsonSerializer.Deserialize(new JsonTextReader(new StringReader("{}")), typeof(Store));
|
||||
Assert.AreEqual("\r\n\t\f\b?{\\r\\n\"\'", s2.Escape);
|
||||
|
||||
Store s3 = (Store)jsonSerializer.Deserialize(new JsonTextReader(new StringReader(@"{""Escape"":null}")), typeof(Store));
|
||||
Assert.AreEqual("\r\n\t\f\b?{\\r\\n\"\'", s3.Escape);
|
||||
|
||||
Store s4 = (Store)jsonSerializer.Deserialize(new JsonTextReader(new StringReader(@"{""Color"":2,""Establised"":""\/Date(1264071600000+1300)\/"",""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""ExpiryDate"":""\/Date(949485690000+1300)\/"",""Price"":0},{""Name"":""Alien"",""ExpiryDate"":""\/Date(946638000000)\/"",""Price"":0.0}]}")), typeof(Store));
|
||||
Assert.AreEqual(s1.Establised, s3.Establised);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeObject()
|
||||
{
|
||||
@@ -860,49 +837,6 @@ keyword such as type of business.""
|
||||
Assert.AreEqual(@"{""Id"":0}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultValueAttributeTest()
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass(),
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{""TestField1"":0,""TestProperty1"":null}", json);
|
||||
|
||||
json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass { TestField1 = int.MinValue, TestProperty1 = "NotDefault" },
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{""TestField1"":-2147483648,""TestProperty1"":""NotDefault""}", json);
|
||||
|
||||
json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass { TestField1 = 21, TestProperty1 = "NotDefault" },
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{""TestProperty1"":""NotDefault""}", json);
|
||||
|
||||
json = JsonConvert.SerializeObject(new DefaultValueAttributeTestClass { TestField1 = 21, TestProperty1 = "TestProperty1Value" },
|
||||
Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
Assert.AreEqual(@"{}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeInvoice()
|
||||
{
|
||||
Invoice invoice = new Invoice
|
||||
{
|
||||
Company = "Acme Ltd.",
|
||||
Amount = 50.0m,
|
||||
Paid = false
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(invoice);
|
||||
|
||||
Console.WriteLine(json);
|
||||
// {"Company":"Acme Ltd.","Amount":50.0,"Paid":false,"PaidDate":null}
|
||||
|
||||
json = JsonConvert.SerializeObject(invoice,
|
||||
Formatting.None,
|
||||
new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
|
||||
|
||||
Console.WriteLine(json);
|
||||
// {"Company":"Acme Ltd.","Amount":50.0}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeNullable()
|
||||
{
|
||||
@@ -1024,7 +958,7 @@ keyword such as type of business.""
|
||||
public void RequiredMembersClassWithNullValues()
|
||||
{
|
||||
string json = @"{
|
||||
""FirstName"": null,
|
||||
""FirstName"": ""I can't be null bro!"",
|
||||
""MiddleName"": null,
|
||||
""LastName"": null,
|
||||
""BirthDate"": ""\/Date(977309755000)\/""
|
||||
@@ -1032,7 +966,23 @@ keyword such as type of business.""
|
||||
|
||||
RequiredMembersClass c = JsonConvert.DeserializeObject<RequiredMembersClass>(json);
|
||||
|
||||
Assert.AreEqual(null, c.FirstName);
|
||||
Assert.AreEqual("I can't be null bro!", c.FirstName);
|
||||
Assert.AreEqual(null, c.MiddleName);
|
||||
Assert.AreEqual(null, c.LastName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = "Required property 'FirstName' expects a value but got null.")]
|
||||
public void RequiredMembersClassNullRequiredValueProperty()
|
||||
{
|
||||
string json = @"{
|
||||
""FirstName"": null,
|
||||
""MiddleName"": null,
|
||||
""LastName"": null,
|
||||
""BirthDate"": ""\/Date(977309755000)\/""
|
||||
}";
|
||||
|
||||
JsonConvert.DeserializeObject<RequiredMembersClass>(json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -1815,20 +1765,151 @@ keyword such as type of business.""
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeNullableListWithNullss()
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot deserialize JSON array into type 'Newtonsoft.Json.Tests.TestObjects.Person'.")]
|
||||
public void CannotDeserializeArrayIntoObject()
|
||||
{
|
||||
//JavaScriptSerializer s = new JavaScriptSerializer();
|
||||
//s.Deserialize<List<decimal?>>("[ 3.3, null, 1.1 ] ");
|
||||
string json = @"[]";
|
||||
|
||||
//DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List<decimal?>));
|
||||
//s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes("[ 3.3, null, 1.1 ] ")));
|
||||
JsonConvert.DeserializeObject<Person>(json);
|
||||
}
|
||||
|
||||
List<decimal?> l = JsonConvert.DeserializeObject<List<decimal?>>("[ 3.3, null, 1.1 ] ");
|
||||
Assert.AreEqual(3, l.Count);
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot deserialize JSON object into type 'System.Collections.Generic.List`1[Newtonsoft.Json.Tests.TestObjects.Person]'.")]
|
||||
public void CannotDeserializeObjectIntoArray()
|
||||
{
|
||||
string json = @"{}";
|
||||
|
||||
Assert.AreEqual(3.3m, l[0]);
|
||||
Assert.AreEqual(null, l[1]);
|
||||
Assert.AreEqual(1.1m, l[2]);
|
||||
JsonConvert.DeserializeObject<List<Person>>(json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot populate JSON array onto type 'Newtonsoft.Json.Tests.TestObjects.Person'.")]
|
||||
public void CannotPopulateArrayIntoObject()
|
||||
{
|
||||
string json = @"[]";
|
||||
|
||||
JsonConvert.PopulateObject(json, new Person());
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Cannot populate JSON object onto type 'System.Collections.Generic.List`1[Newtonsoft.Json.Tests.TestObjects.Person]'.")]
|
||||
public void CannotPopulateObjectIntoArray()
|
||||
{
|
||||
string json = @"{}";
|
||||
|
||||
JsonConvert.PopulateObject(json, new List<Person>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeEmptyString()
|
||||
{
|
||||
string json = @"{""Name"":""""}";
|
||||
|
||||
Person p = JsonConvert.DeserializeObject<Person>(json);
|
||||
Assert.AreEqual("", p.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error getting value from 'ReadTimeout' on 'System.IO.MemoryStream'.")]
|
||||
public void SerializePropertyGetError()
|
||||
{
|
||||
JsonConvert.SerializeObject(new MemoryStream());
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error setting value to 'ReadTimeout' on 'System.IO.MemoryStream'.")]
|
||||
public void DeserializePropertySetError()
|
||||
{
|
||||
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:0}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error converting value """" to type 'System.Int32'.")]
|
||||
public void DeserializeEnsureTypeEmptyStringToIntError()
|
||||
{
|
||||
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:''}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"Error converting value {null} to type 'System.Int32'.")]
|
||||
public void DeserializeEnsureTypeNullToIntError()
|
||||
{
|
||||
JsonConvert.DeserializeObject<MemoryStream>("{ReadTimeout:null}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeGenericListOfStrings()
|
||||
{
|
||||
List<String> strings = new List<String>();
|
||||
|
||||
strings.Add("str_1");
|
||||
strings.Add("str_2");
|
||||
strings.Add("str_3");
|
||||
|
||||
string json = JsonConvert.SerializeObject(strings);
|
||||
Assert.AreEqual(@"[""str_1"",""str_2"",""str_3""]", json);
|
||||
}
|
||||
|
||||
public class ConstructorReadonlyFields
|
||||
{
|
||||
public readonly string A;
|
||||
public readonly int B;
|
||||
|
||||
public ConstructorReadonlyFields(string a, int b)
|
||||
{
|
||||
A = a;
|
||||
B = b;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConstructorReadonlyFieldsTest()
|
||||
{
|
||||
ConstructorReadonlyFields c1 = new ConstructorReadonlyFields("String!", int.MaxValue);
|
||||
string json = JsonConvert.SerializeObject(c1, Formatting.Indented);
|
||||
Assert.AreEqual(@"{
|
||||
""A"": ""String!"",
|
||||
""B"": 2147483647
|
||||
}", json);
|
||||
|
||||
ConstructorReadonlyFields c2 = JsonConvert.DeserializeObject<ConstructorReadonlyFields>(json);
|
||||
Assert.AreEqual("String!", c2.A);
|
||||
Assert.AreEqual(int.MaxValue, c2.B);
|
||||
}
|
||||
|
||||
public struct StructTest
|
||||
{
|
||||
public string StringProperty { get; set; }
|
||||
public string StringField;
|
||||
public int IntProperty { get; set; }
|
||||
public int IntField;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeStruct()
|
||||
{
|
||||
StructTest structTest = new StructTest
|
||||
{
|
||||
StringProperty = "StringProperty!",
|
||||
StringField = "StringField",
|
||||
IntProperty = 5,
|
||||
IntField = 10
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(structTest, Formatting.Indented);
|
||||
Console.WriteLine(json);
|
||||
Assert.AreEqual(@"{
|
||||
""StringField"": ""StringField"",
|
||||
""IntField"": 10,
|
||||
""StringProperty"": ""StringProperty!"",
|
||||
""IntProperty"": 5
|
||||
}", json);
|
||||
|
||||
StructTest deserialized = JsonConvert.DeserializeObject<StructTest>(json);
|
||||
Assert.AreEqual(structTest.StringProperty, deserialized.StringProperty);
|
||||
Assert.AreEqual(structTest.StringField, deserialized.StringField);
|
||||
Assert.AreEqual(structTest.IntProperty, deserialized.IntProperty);
|
||||
Assert.AreEqual(structTest.IntField, deserialized.IntField);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Tests.TestObjects;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Serialization
|
||||
{
|
||||
public class NullValueHandlingTests : TestFixtureBase
|
||||
{
|
||||
[Test]
|
||||
public void NullValueHandlingSerialization()
|
||||
{
|
||||
Store s1 = new Store();
|
||||
|
||||
JsonSerializer jsonSerializer = new JsonSerializer();
|
||||
jsonSerializer.NullValueHandling = NullValueHandling.Ignore;
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
jsonSerializer.Serialize(sw, s1);
|
||||
|
||||
//JsonConvert.ConvertDateTimeToJavaScriptTicks(s1.Establised.DateTime)
|
||||
|
||||
Assert.AreEqual(@"{""Color"":4,""Establised"":""\/Date(1264122061000+0000)\/"",""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""ExpiryDate"":""\/Date(949532490000)\/"",""Price"":0.0},{""Name"":""Alien"",""ExpiryDate"":""\/Date(946684800000)\/"",""Price"":0.0}]}", sw.GetStringBuilder().ToString());
|
||||
|
||||
Store s2 = (Store)jsonSerializer.Deserialize(new JsonTextReader(new StringReader("{}")), typeof(Store));
|
||||
Assert.AreEqual("\r\n\t\f\b?{\\r\\n\"\'", s2.Escape);
|
||||
|
||||
Store s3 = (Store)jsonSerializer.Deserialize(new JsonTextReader(new StringReader(@"{""Escape"":null}")), typeof(Store));
|
||||
Assert.AreEqual("\r\n\t\f\b?{\\r\\n\"\'", s3.Escape);
|
||||
|
||||
Store s4 = (Store)jsonSerializer.Deserialize(new JsonTextReader(new StringReader(@"{""Color"":2,""Establised"":""\/Date(1264071600000+1300)\/"",""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""ExpiryDate"":""\/Date(949485690000+1300)\/"",""Price"":0},{""Name"":""Alien"",""ExpiryDate"":""\/Date(946638000000)\/"",""Price"":0.0}]}")), typeof(Store));
|
||||
Assert.AreEqual(s1.Establised, s3.Establised);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NullValueHandlingBlogPost()
|
||||
{
|
||||
Movie movie = new Movie();
|
||||
movie.Name = "Bad Boys III";
|
||||
movie.Description = "It's no Bad Boys";
|
||||
|
||||
string included = JsonConvert.SerializeObject(movie,
|
||||
Formatting.Indented,
|
||||
new JsonSerializerSettings { });
|
||||
|
||||
// {
|
||||
// "Name": "Bad Boys III",
|
||||
// "Description": "It's no Bad Boys",
|
||||
// "Classification": null,
|
||||
// "Studio": null,
|
||||
// "ReleaseDate": null,
|
||||
// "ReleaseCountries": null
|
||||
// }
|
||||
|
||||
string ignored = JsonConvert.SerializeObject(movie,
|
||||
Formatting.Indented,
|
||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
|
||||
// {
|
||||
// "Name": "Bad Boys III",
|
||||
// "Description": "It's no Bad Boys"
|
||||
// }
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Name"": ""Bad Boys III"",
|
||||
""Description"": ""It's no Bad Boys"",
|
||||
""Classification"": null,
|
||||
""Studio"": null,
|
||||
""ReleaseDate"": null,
|
||||
""ReleaseCountries"": null
|
||||
}", included);
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""Name"": ""Bad Boys III"",
|
||||
""Description"": ""It's no Bad Boys""
|
||||
}", ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,12 +327,13 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
|
||||
serializer.Deserialize(new StringReader(json), typeof(List<List<DateTime>>));
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, errors.Count);
|
||||
Assert.AreEqual("Could not cast or convert from System.String to System.DateTime.", errors[0]);
|
||||
Assert.AreEqual(@"Error converting value ""kjhkjhkjhkjh"" to type 'System.DateTime'.", errors[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT && !NET20
|
||||
#if !PocketPC && !NET20
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -61,7 +61,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
Assert.AreEqual("This value was reset after serialization.", obj.Member2);
|
||||
Assert.AreEqual("This is a nonserialized value", obj.Member3);
|
||||
Assert.AreEqual(null, obj.Member4);
|
||||
Assert.AreEqual("Error message for member Member6 = Exception has been thrown by the target of an invocation.", obj.Member5);
|
||||
Assert.AreEqual("Error message for member Member6 = Error getting value from 'Member6' on 'Newtonsoft.Json.Tests.TestObjects.SerializationEventTestObject'.", obj.Member5);
|
||||
|
||||
JObject o = JObject.Parse(@"{
|
||||
""Member1"": 11,
|
||||
@@ -76,7 +76,7 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
Assert.AreEqual("This value went into the data file during serialization.", obj.Member2);
|
||||
Assert.AreEqual("This value was set during deserialization", obj.Member3);
|
||||
Assert.AreEqual("This value was set after deserialization.", obj.Member4);
|
||||
Assert.AreEqual("Error message for member Member6 = Exception has been thrown by the target of an invocation.", obj.Member5);
|
||||
Assert.AreEqual("Error message for member Member6 = Error setting value to 'Member6' on 'Newtonsoft.Json.Tests.TestObjects.SerializationEventTestObject'.", obj.Member5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.TestObjects
|
||||
{
|
||||
public class Car
|
||||
{
|
||||
// included in JSON
|
||||
public string Model { get; set; }
|
||||
public DateTime Year { get; set; }
|
||||
public List<string> Features { get; set; }
|
||||
|
||||
// ignored
|
||||
[JsonIgnore]
|
||||
public DateTime LastModified { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace Newtonsoft.Json.Tests.TestObjects
|
||||
{
|
||||
public class CircularReferenceClass
|
||||
{
|
||||
[JsonProperty(IsRequired = true)]
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string Name { get; set; }
|
||||
public CircularReferenceClass Child { get; set; }
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Newtonsoft.Json.Tests.TestObjects
|
||||
[JsonObject(Id = "MyExplicitId")]
|
||||
public class CircularReferenceWithIdClass
|
||||
{
|
||||
[JsonProperty(IsRequired = true)]
|
||||
[JsonProperty(Required = Required.AllowNull)]
|
||||
public string Name { get; set; }
|
||||
public CircularReferenceWithIdClass Child { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.TestObjects
|
||||
{
|
||||
[DataContract]
|
||||
public class Computer
|
||||
{
|
||||
// included in JSON
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
[DataMember]
|
||||
public decimal SalePrice { get; set; }
|
||||
|
||||
// ignored
|
||||
public string Manufacture { get; set; }
|
||||
public int StockCount { get; set; }
|
||||
public decimal WholeSalePrice { get; set; }
|
||||
public DateTime NextShipmentDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,16 @@ namespace Newtonsoft.Json.Tests.TestObjects
|
||||
{
|
||||
public string Company { get; set; }
|
||||
public decimal Amount { get; set; }
|
||||
[DefaultValue(false)]
|
||||
|
||||
// false is default value of bool
|
||||
public bool Paid { get; set; }
|
||||
[DefaultValue(null)]
|
||||
// null is default value of nullable
|
||||
public DateTime? PaidDate { get; set; }
|
||||
|
||||
// customize default values
|
||||
[DefaultValue(30)]
|
||||
public int FollowUpDays { get; set; }
|
||||
[DefaultValue("")]
|
||||
public string FollowUpEmailAddress { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Tests.TestObjects
|
||||
{
|
||||
public class Movie
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Classification { get; set; }
|
||||
public string Studio { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public List<string> ReleaseCountries { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -32,16 +32,16 @@ namespace Newtonsoft.Json.Tests.TestObjects
|
||||
{
|
||||
public class RequiredMembersClass
|
||||
{
|
||||
[JsonProperty(IsRequired = true)]
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string FirstName { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
public string MiddleName { get; set; }
|
||||
|
||||
[JsonProperty(IsRequired = true)]
|
||||
[JsonProperty(Required = Required.AllowNull)]
|
||||
public string LastName { get; set; }
|
||||
|
||||
[JsonProperty(IsRequired = true)]
|
||||
[JsonProperty(Required = Required.Default)]
|
||||
public DateTime BirthDate { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Tests.Serialization;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT && !NET20
|
||||
#if !PocketPC && !NET20
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
@@ -37,9 +37,11 @@ namespace Newtonsoft.Json.Tests.TestObjects
|
||||
public int[] RoomsPerFloor = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
public bool Open = false;
|
||||
public char Symbol = '@';
|
||||
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
|
||||
public List<string> Mottos = new List<string>();
|
||||
public decimal Cost = 100980.1M;
|
||||
public string Escape = "\r\n\t\f\b?{\\r\\n\"\'";
|
||||
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
|
||||
public List<Product> product = new List<Product>();
|
||||
|
||||
public Store()
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if !SILVERLIGHT && !PocketPC && !NET20
|
||||
using System.Data.Linq;
|
||||
#endif
|
||||
#if !SILVERLIGHT
|
||||
using System.Data.SqlTypes;
|
||||
#endif
|
||||
@@ -38,11 +35,22 @@ using Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
#if !SILVERLIGHT && !PocketPC && !NET20
|
||||
internal interface IBinary
|
||||
{
|
||||
byte[] ToArray();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Converts a binary value to and from a base 64 string value.
|
||||
/// </summary>
|
||||
public class BinaryConverter : JsonConverter
|
||||
{
|
||||
#if !SILVERLIGHT && !PocketPC && !NET20
|
||||
private const string BinaryTypeName = "System.Data.Linq.Binary";
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
@@ -68,8 +76,11 @@ namespace Newtonsoft.Json.Converters
|
||||
private byte[] GetByteArray(object value)
|
||||
{
|
||||
#if !SILVERLIGHT && !PocketPC && !NET20
|
||||
if (value is Binary)
|
||||
return ((Binary)value).ToArray();
|
||||
if (value.GetType().AssignableToTypeName(BinaryTypeName))
|
||||
{
|
||||
IBinary binary = DynamicWrapper.CreateWrapper<IBinary>(value);
|
||||
return binary.ToArray();
|
||||
}
|
||||
#endif
|
||||
#if !SILVERLIGHT
|
||||
if (value is SqlBinary)
|
||||
@@ -110,8 +121,8 @@ namespace Newtonsoft.Json.Converters
|
||||
return data;
|
||||
|
||||
#if !SILVERLIGHT && !PocketPC && !NET20
|
||||
if (typeof(Binary).IsAssignableFrom(t))
|
||||
return new Binary(data);
|
||||
if (t.AssignableToTypeName(BinaryTypeName))
|
||||
return Activator.CreateInstance(t, data);
|
||||
#endif
|
||||
#if !SILVERLIGHT
|
||||
if (typeof(SqlBinary).IsAssignableFrom(t))
|
||||
@@ -137,7 +148,7 @@ namespace Newtonsoft.Json.Converters
|
||||
return true;
|
||||
|
||||
#if !SILVERLIGHT && !PocketPC && !NET20
|
||||
if (typeof(Binary).IsAssignableFrom(t))
|
||||
if (t.AssignableToTypeName(BinaryTypeName))
|
||||
return true;
|
||||
#endif
|
||||
#if !SILVERLIGHT
|
||||
|
||||
@@ -26,17 +26,28 @@
|
||||
#if !PocketPC && !SILVERLIGHT && !NET20
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
internal interface IEntityKeyMember
|
||||
{
|
||||
string Key { get; set; }
|
||||
object Value { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an Entity Framework EntityKey to and from JSON.
|
||||
/// </summary>
|
||||
public class EntityKeyMemberConverter : JsonConverter
|
||||
{
|
||||
private const string EntityKeyMemberFullTypeName = "System.Data.EntityKeyMember";
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
@@ -45,7 +56,7 @@ namespace Newtonsoft.Json.Converters
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
EntityKeyMember entityKeyMember = (EntityKeyMember) value;
|
||||
IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper<IEntityKeyMember>(value);
|
||||
Type keyType = (entityKeyMember.Value != null) ? entityKeyMember.Value.GetType() : null;
|
||||
|
||||
writer.WriteStartObject();
|
||||
@@ -95,7 +106,7 @@ namespace Newtonsoft.Json.Converters
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
|
||||
{
|
||||
EntityKeyMember entityKeyMember = new EntityKeyMember();
|
||||
IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper<IEntityKeyMember>(Activator.CreateInstance(objectType));
|
||||
|
||||
ReadAndAssertProperty(reader, "Key");
|
||||
ReadAndAssert(reader);
|
||||
@@ -113,7 +124,7 @@ namespace Newtonsoft.Json.Converters
|
||||
|
||||
ReadAndAssert(reader);
|
||||
|
||||
return entityKeyMember;
|
||||
return DynamicWrapper.GetUnderlyingObject(entityKeyMember);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,7 +136,7 @@ namespace Newtonsoft.Json.Converters
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return typeof(EntityKeyMember).IsAssignableFrom(objectType);
|
||||
return (objectType.AssignableToTypeName(EntityKeyMemberFullTypeName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -13,6 +13,7 @@ namespace Newtonsoft.Json
|
||||
internal NullValueHandling? _nullValueHandling;
|
||||
internal DefaultValueHandling? _defaultValueHandling;
|
||||
internal ReferenceLoopHandling? _referenceLoopHandling;
|
||||
internal ObjectCreationHandling? _objectCreationHandling;
|
||||
internal bool? _isReference;
|
||||
|
||||
/// <summary>
|
||||
@@ -45,6 +46,16 @@ namespace Newtonsoft.Json
|
||||
set { _referenceLoopHandling = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the object creation handling used when deserializing this property.
|
||||
/// </summary>
|
||||
/// <value>The object creation handling.</value>
|
||||
public ObjectCreationHandling ObjectCreationHandling
|
||||
{
|
||||
get { return _objectCreationHandling ?? default(ObjectCreationHandling); }
|
||||
set { _objectCreationHandling = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this property's value is serialized as a reference.
|
||||
/// </summary>
|
||||
@@ -65,9 +76,9 @@ namespace Newtonsoft.Json
|
||||
/// Gets or sets a value indicating whether this property is required.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this property is required; otherwise, <c>false</c>.
|
||||
/// A value indicating whether this property is required.
|
||||
/// </value>
|
||||
public bool IsRequired { get; set; }
|
||||
public Required Required { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPropertyAttribute"/> class.
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
<Compile Include="Linq\JProperty.cs" />
|
||||
<Compile Include="Linq\JValue.cs" />
|
||||
<Compile Include="PreserveReferencesHandling.cs" />
|
||||
<Compile Include="Required.cs" />
|
||||
<Compile Include="Schema\Extensions.cs" />
|
||||
<Compile Include="Schema\JsonSchemaException.cs" />
|
||||
<Compile Include="Schema\JsonSchemaModel.cs" />
|
||||
@@ -128,10 +129,12 @@
|
||||
<Compile Include="Serialization\DefaultContractResolver.cs" />
|
||||
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
|
||||
<Compile Include="Serialization\DefaultSerializationBinder.cs" />
|
||||
<Compile Include="Serialization\DynamicValueProvider.cs" />
|
||||
<Compile Include="Serialization\ErrorContext.cs" />
|
||||
<Compile Include="Serialization\ErrorEventArgs.cs" />
|
||||
<Compile Include="Serialization\IContractResolver.cs" />
|
||||
<Compile Include="Serialization\IReferenceResolver.cs" />
|
||||
<Compile Include="Serialization\IValueProvider.cs" />
|
||||
<Compile Include="Serialization\JsonArrayContract.cs" />
|
||||
<Compile Include="Serialization\JsonContract.cs" />
|
||||
<Compile Include="Serialization\JsonDictionaryContract.cs" />
|
||||
@@ -153,6 +156,7 @@
|
||||
<Compile Include="Serialization\JsonSerializerProxy.cs" />
|
||||
<Compile Include="Serialization\JsonTypeReflector.cs" />
|
||||
<Compile Include="Serialization\OnErrorAttribute.cs" />
|
||||
<Compile Include="Serialization\ReflectionValueProvider.cs" />
|
||||
<Compile Include="StreamingContext.cs" />
|
||||
<Compile Include="TypeNameHandling.cs" />
|
||||
<Compile Include="Utilities\BidirectionalDictionary.cs" />
|
||||
@@ -160,6 +164,7 @@
|
||||
<Compile Include="Utilities\CollectionWrapper.cs" />
|
||||
<Compile Include="Utilities\DateTimeUtils.cs" />
|
||||
<Compile Include="Utilities\DictionaryWrapper.cs" />
|
||||
<Compile Include="Utilities\DynamicWrapper.cs" />
|
||||
<Compile Include="Utilities\EnumUtils.cs" />
|
||||
<Compile Include="Utilities\EnumValue.cs" />
|
||||
<Compile Include="Utilities\EnumValues.cs" />
|
||||
@@ -168,6 +173,7 @@
|
||||
<Compile Include="JsonWriter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utilities\CollectionUtils.cs" />
|
||||
<Compile Include="Utilities\LateBoundDelegateFactory.cs" />
|
||||
<Compile Include="Utilities\ListWrapper.cs" />
|
||||
<Compile Include="Utilities\MathUtils.cs" />
|
||||
<Compile Include="Utilities\MiscellaneousUtils.cs" />
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
<Compile Include="Linq\ComponentModel\JTypeDescriptionProvider.cs" />
|
||||
<Compile Include="Linq\ComponentModel\JTypeDescriptor.cs" />
|
||||
<Compile Include="Linq\JPath.cs" />
|
||||
<Compile Include="Required.cs" />
|
||||
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
|
||||
<Compile Include="PreserveReferencesHandling.cs" />
|
||||
<Compile Include="IJsonLineInfo.cs" />
|
||||
@@ -146,9 +147,11 @@
|
||||
<Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
|
||||
<Compile Include="Serialization\DefaultContractResolver.cs" />
|
||||
<Compile Include="Serialization\DefaultSerializationBinder.cs" />
|
||||
<Compile Include="Serialization\DynamicValueProvider.cs" />
|
||||
<Compile Include="Serialization\ErrorContext.cs" />
|
||||
<Compile Include="Serialization\ErrorEventArgs.cs" />
|
||||
<Compile Include="Serialization\IContractResolver.cs" />
|
||||
<Compile Include="Serialization\IValueProvider.cs" />
|
||||
<Compile Include="Serialization\JsonArrayContract.cs" />
|
||||
<Compile Include="Serialization\JsonContract.cs" />
|
||||
<Compile Include="Serialization\JsonDictionaryContract.cs" />
|
||||
@@ -171,6 +174,9 @@
|
||||
<Compile Include="Serialization\JsonTypeReflector.cs" />
|
||||
<Compile Include="Serialization\CachedAttributeGetter.cs" />
|
||||
<Compile Include="Serialization\OnErrorAttribute.cs" />
|
||||
<Compile Include="Serialization\ReflectionValueProvider.cs" />
|
||||
<Compile Include="Utilities\DynamicWrapper.cs" />
|
||||
<Compile Include="Utilities\LateBoundDelegateFactory.cs" />
|
||||
<Compile Include="Utilities\ThreadSafeStore.cs" />
|
||||
<Compile Include="TypeNameHandling.cs" />
|
||||
<Compile Include="Utilities\BidirectionalDictionary.cs" />
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
<SilverlightApplication>false</SilverlightApplication>
|
||||
<ValidateXaml>true</ValidateXaml>
|
||||
<ThrowErrorsInValidation>false</ThrowErrorsInValidation>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -110,16 +115,19 @@
|
||||
<Compile Include="PreserveReferencesHandling.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ReferenceLoopHandling.cs" />
|
||||
<Compile Include="Required.cs" />
|
||||
<Compile Include="SerializationBinder.cs" />
|
||||
<Compile Include="Serialization\CachedAttributeGetter.cs" />
|
||||
<Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
|
||||
<Compile Include="Serialization\DefaultContractResolver.cs" />
|
||||
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
|
||||
<Compile Include="Serialization\DefaultSerializationBinder.cs" />
|
||||
<Compile Include="Serialization\DynamicValueProvider.cs" />
|
||||
<Compile Include="Serialization\ErrorContext.cs" />
|
||||
<Compile Include="Serialization\ErrorEventArgs.cs" />
|
||||
<Compile Include="Serialization\IContractResolver.cs" />
|
||||
<Compile Include="Serialization\IReferenceResolver.cs" />
|
||||
<Compile Include="Serialization\IValueProvider.cs" />
|
||||
<Compile Include="Serialization\JsonArrayContract.cs" />
|
||||
<Compile Include="Serialization\JsonContract.cs" />
|
||||
<Compile Include="Serialization\JsonDictionaryContract.cs" />
|
||||
@@ -131,6 +139,7 @@
|
||||
<Compile Include="Serialization\JsonSerializerInternalReader.cs" />
|
||||
<Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
|
||||
<Compile Include="Serialization\OnErrorAttribute.cs" />
|
||||
<Compile Include="Serialization\ReflectionValueProvider.cs" />
|
||||
<Compile Include="StreamingContext.cs" />
|
||||
<Compile Include="TypeNameHandling.cs" />
|
||||
<Compile Include="Utilities\BidirectionalDictionary.cs" />
|
||||
@@ -139,10 +148,12 @@
|
||||
<Compile Include="Utilities\ConvertUtils.cs" />
|
||||
<Compile Include="Utilities\DateTimeUtils.cs" />
|
||||
<Compile Include="Utilities\DictionaryWrapper.cs" />
|
||||
<Compile Include="Utilities\DynamicWrapper.cs" />
|
||||
<Compile Include="Utilities\EnumUtils.cs" />
|
||||
<Compile Include="Utilities\EnumValue.cs" />
|
||||
<Compile Include="Utilities\EnumValues.cs" />
|
||||
<Compile Include="Utilities\JavaScriptUtils.cs" />
|
||||
<Compile Include="Utilities\LateBoundDelegateFactory.cs" />
|
||||
<Compile Include="Utilities\ListWrapper.cs" />
|
||||
<Compile Include="Utilities\MathUtils.cs" />
|
||||
<Compile Include="Utilities\MiscellaneousUtils.cs" />
|
||||
@@ -169,7 +180,7 @@
|
||||
<Compile Include="Schema\JsonSchemaType.cs" />
|
||||
<Compile Include="Serialization\JsonTypeReflector.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\v3.0\Microsoft.Silverlight.CSharp.targets" Condition="" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -72,12 +72,6 @@
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.Entity">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Serialization">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
@@ -94,6 +88,8 @@
|
||||
<Compile Include="Converters\StringEnumConverter.cs" />
|
||||
<Compile Include="ConstructorHandling.cs" />
|
||||
<Compile Include="Linq\JPath.cs" />
|
||||
<Compile Include="Required.cs" />
|
||||
<Compile Include="Serialization\DynamicValueProvider.cs" />
|
||||
<Compile Include="Serialization\ErrorEventArgs.cs" />
|
||||
<Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
|
||||
<Compile Include="Linq\ComponentModel\JTypeDescriptionProvider.cs" />
|
||||
@@ -158,6 +154,7 @@
|
||||
<Compile Include="Serialization\DefaultSerializationBinder.cs" />
|
||||
<Compile Include="Serialization\ErrorContext.cs" />
|
||||
<Compile Include="Serialization\IContractResolver.cs" />
|
||||
<Compile Include="Serialization\IValueProvider.cs" />
|
||||
<Compile Include="Serialization\JsonArrayContract.cs" />
|
||||
<Compile Include="Serialization\JsonContract.cs" />
|
||||
<Compile Include="Serialization\JsonDictionaryContract.cs" />
|
||||
@@ -179,7 +176,10 @@
|
||||
<Compile Include="Serialization\JsonSerializerProxy.cs" />
|
||||
<Compile Include="Serialization\JsonTypeReflector.cs" />
|
||||
<Compile Include="Serialization\CachedAttributeGetter.cs" />
|
||||
<Compile Include="Serialization\ReflectionValueProvider.cs" />
|
||||
<Compile Include="Serialization\OnErrorAttribute.cs" />
|
||||
<Compile Include="Utilities\DynamicWrapper.cs" />
|
||||
<Compile Include="Utilities\LateBoundDelegateFactory.cs" />
|
||||
<Compile Include="Utilities\ThreadSafeStore.cs" />
|
||||
<Compile Include="TypeNameHandling.cs" />
|
||||
<Compile Include="Utilities\BidirectionalDictionary.cs" />
|
||||
@@ -220,5 +220,8 @@
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Dynamic.snk" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -51,6 +51,8 @@ using System.Security;
|
||||
|
||||
#endif
|
||||
|
||||
[assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")]
|
||||
|
||||
|
||||
|
||||
[assembly: AssemblyDescription("")]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
public enum Required
|
||||
{
|
||||
Default,
|
||||
AllowNull,
|
||||
Always
|
||||
}
|
||||
}
|
||||
@@ -164,7 +164,7 @@ namespace Newtonsoft.Json.Schema
|
||||
|
||||
_resolver = resolver;
|
||||
|
||||
return GenerateInternal(type, !rootSchemaNullable);
|
||||
return GenerateInternal(type, (!rootSchemaNullable) ? Required.Always : Required.Default);
|
||||
}
|
||||
|
||||
private string GetTitle(Type type)
|
||||
@@ -214,7 +214,7 @@ namespace Newtonsoft.Json.Schema
|
||||
}
|
||||
}
|
||||
|
||||
private JsonSchema GenerateInternal(Type type, bool valueRequired)
|
||||
private JsonSchema GenerateInternal(Type type, Required valueRequired)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "type");
|
||||
|
||||
@@ -256,7 +256,7 @@ namespace Newtonsoft.Json.Schema
|
||||
// can be converted to a string
|
||||
if (typeof (IConvertible).IsAssignableFrom(keyType))
|
||||
{
|
||||
CurrentSchema.AdditionalProperties = GenerateInternal(valueType, false);
|
||||
CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,7 +274,7 @@ namespace Newtonsoft.Json.Schema
|
||||
if (collectionItemType != null)
|
||||
{
|
||||
CurrentSchema.Items = new List<JsonSchema>();
|
||||
CurrentSchema.Items.Add(GenerateInternal(collectionItemType, !allowNullItem));
|
||||
CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -295,8 +295,7 @@ namespace Newtonsoft.Json.Schema
|
||||
{
|
||||
if (!property.Ignored)
|
||||
{
|
||||
Type propertyMemberType = ReflectionUtils.GetMemberUnderlyingType(property.Member);
|
||||
JsonSchema propertySchema = GenerateInternal(propertyMemberType, property.Required);
|
||||
JsonSchema propertySchema = GenerateInternal(property.PropertyType, property.Required);
|
||||
|
||||
if (property.DefaultValue != null)
|
||||
propertySchema.Default = JToken.FromObject(property.DefaultValue);
|
||||
@@ -336,10 +335,10 @@ namespace Newtonsoft.Json.Schema
|
||||
return ((value & flag) == flag);
|
||||
}
|
||||
|
||||
private JsonSchemaType GetJsonSchemaType(Type type, bool valueRequired)
|
||||
private JsonSchemaType GetJsonSchemaType(Type type, Required valueRequired)
|
||||
{
|
||||
JsonSchemaType schemaType = JsonSchemaType.None;
|
||||
if (!valueRequired && ReflectionUtils.IsNullable(type))
|
||||
if (valueRequired != Required.Always && ReflectionUtils.IsNullable(type))
|
||||
{
|
||||
schemaType = JsonSchemaType.Null;
|
||||
if (ReflectionUtils.IsNullableType(type))
|
||||
|
||||
@@ -32,9 +32,6 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
#if !PocketPC && !SILVERLIGHT && !NET20
|
||||
using System.Data.Objects.DataClasses;
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
@@ -106,8 +103,9 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT && !NET20
|
||||
Type match;
|
||||
// don't include EntityKey on entities objects... this is a bit hacky
|
||||
if (typeof(EntityObject).IsAssignableFrom(objectType))
|
||||
if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", out match))
|
||||
serializableMembers = serializableMembers.Where(ShouldSerializeEntityMember).ToList();
|
||||
#endif
|
||||
|
||||
@@ -120,7 +118,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
|
||||
if (propertyInfo != null)
|
||||
{
|
||||
if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(EntityReference<>))
|
||||
if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().FullName == "System.Data.Objects.DataClasses.EntityReference`1")
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -140,7 +138,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType);
|
||||
contract.Properties.AddRange(CreateProperties(contract));
|
||||
if (contract.DefaultContstructor == null || contract.DefaultContstructor.IsPrivate)
|
||||
if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
|
||||
contract.ParametrizedConstructor = GetParametrizedConstructor(objectType);
|
||||
|
||||
return contract;
|
||||
@@ -173,16 +171,32 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
#endif
|
||||
|
||||
contract.DefaultContstructor =
|
||||
ReflectionUtils.GetDefaultConstructor(contract.CreatedType, false) ??
|
||||
ReflectionUtils.GetDefaultConstructor(contract.CreatedType, true);
|
||||
if (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, true)
|
||||
|| contract.CreatedType.IsValueType)
|
||||
{
|
||||
#if !PocketPC
|
||||
contract.DefaultCreator = LateBoundDelegateFactory.CreateDefaultConstructor(contract.CreatedType);
|
||||
#else
|
||||
ConstructorInfo constructorInfo = ReflectionUtils.GetDefaultConstructor(contract.CreatedType, true);
|
||||
|
||||
contract.DefaultCreator = () =>
|
||||
{
|
||||
if (contract.CreatedType.IsValueType)
|
||||
return Activator.CreateInstance(contract.CreatedType);
|
||||
|
||||
return constructorInfo.Invoke(null);
|
||||
};
|
||||
#endif
|
||||
contract.DefaultCreatorNonPublic = (!contract.CreatedType.IsValueType &&
|
||||
ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null);
|
||||
}
|
||||
|
||||
foreach (MethodInfo method in contract.UnderlyingType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
|
||||
{
|
||||
Type prevAttributeType = null;
|
||||
ParameterInfo[] parameters = method.GetParameters();
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT && !NET20
|
||||
#if !PocketPC && !NET20
|
||||
if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), contract.OnSerializing, ref prevAttributeType))
|
||||
{
|
||||
contract.OnSerializing = method;
|
||||
@@ -303,7 +317,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (members == null)
|
||||
throw new JsonSerializationException("Null collection of seralizable members returned.");
|
||||
|
||||
JsonPropertyCollection properties = new JsonPropertyCollection();
|
||||
JsonPropertyCollection properties = new JsonPropertyCollection(contract);
|
||||
|
||||
foreach (MemberInfo member in members)
|
||||
{
|
||||
@@ -325,7 +339,13 @@ namespace Newtonsoft.Json.Serialization
|
||||
protected virtual JsonProperty CreateProperty(JsonObjectContract contract, MemberInfo member)
|
||||
{
|
||||
JsonProperty property = new JsonProperty();
|
||||
property.Member = member;
|
||||
property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member);
|
||||
#if !PocketPC
|
||||
property.ValueProvider = new DynamicValueProvider(member);
|
||||
#else
|
||||
property.ValueProvider = new ReflectionValueProvider(member);
|
||||
#endif
|
||||
property.Converter = JsonTypeReflector.GetConverter(member, property.PropertyType);
|
||||
|
||||
#if !PocketPC && !NET20
|
||||
DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(member.DeclaringType);
|
||||
@@ -353,13 +373,13 @@ namespace Newtonsoft.Json.Serialization
|
||||
property.PropertyName = ResolvePropertyName(mappedName);
|
||||
|
||||
if (propertyAttribute != null)
|
||||
property.Required = propertyAttribute.IsRequired;
|
||||
property.Required = propertyAttribute.Required;
|
||||
#if !PocketPC && !NET20
|
||||
else if (dataMemberAttribute != null)
|
||||
property.Required = dataMemberAttribute.IsRequired;
|
||||
property.Required = (dataMemberAttribute.IsRequired) ? Required.AllowNull : Required.Default;
|
||||
#endif
|
||||
else
|
||||
property.Required = false;
|
||||
property.Required = Required.Default;
|
||||
|
||||
property.Ignored = (hasIgnoreAttribute ||
|
||||
(contract.MemberSerialization == MemberSerialization.OptIn
|
||||
@@ -380,6 +400,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
property.NullValueHandling = (propertyAttribute != null) ? propertyAttribute._nullValueHandling : null;
|
||||
property.DefaultValueHandling = (propertyAttribute != null) ? propertyAttribute._defaultValueHandling : null;
|
||||
property.ReferenceLoopHandling = (propertyAttribute != null) ? propertyAttribute._referenceLoopHandling : null;
|
||||
property.ObjectCreationHandling = (propertyAttribute != null) ? propertyAttribute._objectCreationHandling : null;
|
||||
property.IsReference = (propertyAttribute != null) ? propertyAttribute._isReference : null;
|
||||
|
||||
return property;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#if !PocketPC
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
public class DynamicValueProvider : IValueProvider
|
||||
{
|
||||
private readonly MemberInfo _memberInfo;
|
||||
private Func<object, object> _getter;
|
||||
private Action<object, object> _setter;
|
||||
|
||||
public DynamicValueProvider(MemberInfo memberInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo");
|
||||
_memberInfo = memberInfo;
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_setter == null)
|
||||
_setter = LateBoundDelegateFactory.CreateSet<object>(_memberInfo);
|
||||
|
||||
_setter(target, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public object GetValue(object target)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_getter == null)
|
||||
_getter = LateBoundDelegateFactory.CreateGet<object>(_memberInfo);
|
||||
|
||||
return _getter(target);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
public interface IValueProvider
|
||||
{
|
||||
void SetValue(object target, object value);
|
||||
object GetValue(object target);
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
private bool _isCollectionItemTypeNullableType;
|
||||
private Type _genericCollectionDefinitionType;
|
||||
private Type _genericWrapperType;
|
||||
private ConstructorInfo _genericWrapperConstructor;
|
||||
private MemberHandler<object> _genericWrapperCreator;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonArrayContract"/> class.
|
||||
@@ -80,10 +80,16 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (_genericWrapperType == null)
|
||||
{
|
||||
_genericWrapperType = ReflectionUtils.MakeGenericType(typeof(CollectionWrapper<>), CollectionItemType);
|
||||
_genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType });
|
||||
|
||||
ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType });
|
||||
#if !PocketPC
|
||||
_genericWrapperCreator = LateBoundDelegateFactory.CreateMethodHandler(genericWrapperConstructor);
|
||||
#else
|
||||
_genericWrapperCreator = (target, args) => genericWrapperConstructor.Invoke(new[] { args[0] });
|
||||
#endif
|
||||
}
|
||||
|
||||
return (IWrappedCollection)_genericWrapperConstructor.Invoke(new[] { list });
|
||||
return (IWrappedCollection)_genericWrapperCreator(null, list);
|
||||
}
|
||||
|
||||
private bool IsTypeGenericCollectionInterface(Type type)
|
||||
|
||||
@@ -53,10 +53,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <value>Whether this type contract is serialized as a reference.</value>
|
||||
public bool? IsReference { get; set; }
|
||||
|
||||
private static readonly StreamingContext SerializationStreamingContextParameter = new StreamingContext(StreamingContextStates.All);
|
||||
private static readonly StreamingContext SerializationStreamingContextParameter = new StreamingContext();
|
||||
private static readonly object[] SerializationEventParameterValues = new object[] { SerializationStreamingContextParameter };
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
/// <summary>
|
||||
/// Gets or sets the method called immediately after deserialization of the object.
|
||||
/// </summary>
|
||||
@@ -79,11 +79,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
public MethodInfo OnSerializing { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default contstructor used to create the object.
|
||||
/// </summary>
|
||||
/// <value>The default contstructor.</value>
|
||||
public ConstructorInfo DefaultContstructor { get; set; }
|
||||
public Func<object> DefaultCreator { get; set; }
|
||||
public bool DefaultCreatorNonPublic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the method called when an error is thrown during the serialization of the object.
|
||||
@@ -93,7 +90,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
internal void InvokeOnSerializing(object o)
|
||||
{
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
if (OnSerializing != null)
|
||||
OnSerializing.Invoke(o, SerializationEventParameterValues);
|
||||
#endif
|
||||
@@ -101,7 +98,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
internal void InvokeOnSerialized(object o)
|
||||
{
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
if (OnSerialized != null)
|
||||
OnSerialized.Invoke(o, SerializationEventParameterValues);
|
||||
#endif
|
||||
@@ -109,7 +106,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
internal void InvokeOnDeserializing(object o)
|
||||
{
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
if (OnDeserializing != null)
|
||||
OnDeserializing.Invoke(o, SerializationEventParameterValues);
|
||||
#endif
|
||||
@@ -117,7 +114,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
internal void InvokeOnDeserialized(object o)
|
||||
{
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
if (OnDeserialized != null)
|
||||
OnDeserialized.Invoke(o, SerializationEventParameterValues);
|
||||
#endif
|
||||
|
||||
@@ -39,9 +39,9 @@ namespace Newtonsoft.Json.Serialization
|
||||
internal Type DictionaryKeyType { get; private set; }
|
||||
internal Type DictionaryValueType { get; private set; }
|
||||
|
||||
private Type _genericCollectionDefinitionType;
|
||||
private readonly Type _genericCollectionDefinitionType;
|
||||
private Type _genericWrapperType;
|
||||
private ConstructorInfo _genericWrapperConstructor;
|
||||
private MemberHandler<object> _genericWrapperCreator;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonDictionaryContract"/> class.
|
||||
@@ -83,10 +83,16 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (_genericWrapperType == null)
|
||||
{
|
||||
_genericWrapperType = ReflectionUtils.MakeGenericType(typeof(DictionaryWrapper<,>), DictionaryKeyType, DictionaryValueType);
|
||||
_genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType });
|
||||
|
||||
ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType });
|
||||
#if !PocketPC
|
||||
_genericWrapperCreator = LateBoundDelegateFactory.CreateMethodHandler(genericWrapperConstructor);
|
||||
#else
|
||||
_genericWrapperCreator = (target, args) => genericWrapperConstructor.Invoke(new[] { args[0] });
|
||||
#endif
|
||||
}
|
||||
|
||||
return (IWrappedDictionary)_genericWrapperConstructor.Invoke(new[] { dictionary });
|
||||
return (IWrappedDictionary)_genericWrapperCreator(null, dictionary);
|
||||
}
|
||||
|
||||
private bool IsTypeGenericDictionaryInterface(Type type)
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
public JsonObjectContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
Properties = new JsonPropertyCollection();
|
||||
Properties = new JsonPropertyCollection(this);
|
||||
CreatedType = underlyingType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#endregion
|
||||
|
||||
using System.Reflection;
|
||||
using System;
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
@@ -39,10 +40,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
public string PropertyName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the member.
|
||||
/// Gets the <see cref="IValueProvider"/> that will get and set the <see cref="JsonProperty"/> during serialization.
|
||||
/// </summary>
|
||||
/// <value>The member.</value>
|
||||
public MemberInfo Member { get; set; }
|
||||
/// <value>The <see cref="IValueProvider"/> that will get and set the <see cref="JsonProperty"/> during serialization.</value>
|
||||
public IValueProvider ValueProvider { get; set; }
|
||||
|
||||
public Type PropertyType { get; set; }
|
||||
|
||||
public JsonConverter Converter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="JsonProperty"/> is ignored.
|
||||
@@ -77,8 +82,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="JsonProperty"/> is required.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if required; otherwise, <c>false</c>.</value>
|
||||
public bool Required { get; set; }
|
||||
/// <value>A value indicating whether this <see cref="JsonProperty"/> is required.</value>
|
||||
public Required Required { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this property preserves object references.
|
||||
@@ -105,5 +110,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// </summary>
|
||||
/// <value>The reference loop handling.</value>
|
||||
public ReferenceLoopHandling? ReferenceLoopHandling { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property object creation handling.
|
||||
/// </summary>
|
||||
/// <value>The object creation handling.</value>
|
||||
public ObjectCreationHandling? ObjectCreationHandling { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// </summary>
|
||||
public class JsonPropertyCollection : KeyedCollection<string, JsonProperty>
|
||||
{
|
||||
private readonly JsonObjectContract _contract;
|
||||
|
||||
public JsonPropertyCollection(JsonObjectContract contract)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(contract, "contract");
|
||||
_contract = contract;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When implemented in a derived class, extracts the key from the specified element.
|
||||
/// </summary>
|
||||
@@ -63,7 +71,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (!existingProperty.Ignored)
|
||||
throw new JsonSerializationException(
|
||||
"A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.Member.DeclaringType));
|
||||
"A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _contract.UnderlyingType));
|
||||
|
||||
// remove ignored property so it can be replaced in collection
|
||||
Remove(existingProperty);
|
||||
|
||||
@@ -30,6 +30,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
|
||||
@@ -56,7 +57,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
if (reader.TokenType == JsonToken.StartArray)
|
||||
{
|
||||
PopulateList(CollectionUtils.CreateCollectionWrapper(target), reader, null, GetArrayContract(objectType));
|
||||
if (contract is JsonArrayContract)
|
||||
PopulateList(CollectionUtils.CreateCollectionWrapper(target), reader, null, (JsonArrayContract)contract);
|
||||
else
|
||||
throw new JsonSerializationException("Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.StartObject)
|
||||
{
|
||||
@@ -75,7 +79,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
else if (contract is JsonObjectContract)
|
||||
PopulateObject(target, reader, (JsonObjectContract) contract, id);
|
||||
else
|
||||
throw new JsonSerializationException("Expected a JsonObjectContract or JsonDictionaryContract for type '{0}', got '{1}'.".FormatWith(CultureInfo.InvariantCulture, objectType, contract.GetType()));
|
||||
throw new JsonSerializationException("Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,14 +166,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
return CreateList(reader, objectType, existingValue, null);
|
||||
case JsonToken.Integer:
|
||||
case JsonToken.Float:
|
||||
case JsonToken.String:
|
||||
case JsonToken.Boolean:
|
||||
case JsonToken.Date:
|
||||
// convert empty string to null automatically
|
||||
if (reader.Value is string &&
|
||||
string.IsNullOrEmpty((string)reader.Value) &&
|
||||
return EnsureType(reader.Value, objectType);
|
||||
case JsonToken.String:
|
||||
// convert empty string to null automatically for nullable types
|
||||
if (string.IsNullOrEmpty((string)reader.Value) &&
|
||||
objectType != null &&
|
||||
ReflectionUtils.IsNullable(objectType))
|
||||
ReflectionUtils.IsNullableType(objectType))
|
||||
return null;
|
||||
|
||||
return EnsureType(reader.Value, objectType);
|
||||
@@ -183,7 +187,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (objectType == typeof (DBNull))
|
||||
return DBNull.Value;
|
||||
|
||||
return null;
|
||||
return EnsureType(reader.Value, objectType);
|
||||
case JsonToken.Comment:
|
||||
// ignore
|
||||
break;
|
||||
@@ -297,7 +301,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
return PopulateObject(existingValue, reader, (JsonObjectContract) contract, id);
|
||||
}
|
||||
|
||||
throw new JsonSerializationException("Expected a JsonObjectContract or JsonDictionaryContract for type '{0}', got '{1}'.".FormatWith(CultureInfo.InvariantCulture, objectType, contract.GetType()));
|
||||
throw new JsonSerializationException("Cannot deserialize JSON object into type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
|
||||
private JsonArrayContract GetArrayContract(Type objectType)
|
||||
@@ -308,7 +312,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
JsonArrayContract arrayContract = contract as JsonArrayContract;
|
||||
if (arrayContract == null)
|
||||
throw new JsonSerializationException("Expected a JsonArrayContract for type '{0}', got '{1}'.".FormatWith(CultureInfo.InvariantCulture, objectType, contract.GetType()));
|
||||
throw new JsonSerializationException("Cannot deserialize JSON array into type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
|
||||
return arrayContract;
|
||||
}
|
||||
@@ -345,23 +349,39 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
private object EnsureType(object value, Type targetType)
|
||||
{
|
||||
// do something about null value when the targetType is a valuetype?
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
if (targetType == null)
|
||||
return value;
|
||||
|
||||
Type valueType = value.GetType();
|
||||
Type valueType = ReflectionUtils.GetObjectType(value);
|
||||
|
||||
// type of value and type of target don't match
|
||||
// attempt to convert value's type to target's type
|
||||
if (valueType != targetType)
|
||||
return ConvertUtils.ConvertOrCast(value, CultureInfo.InvariantCulture, targetType);
|
||||
{
|
||||
try
|
||||
{
|
||||
return ConvertUtils.ConvertOrCast(value, CultureInfo.InvariantCulture, targetType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonSerializationException("Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, FormatValueForPrint(value), targetType), ex);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private string FormatValueForPrint(object value)
|
||||
{
|
||||
if (value == null)
|
||||
return "{null}";
|
||||
|
||||
if (value is string)
|
||||
return @"""" + value + @"""";
|
||||
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
private void SetObjectMember(JsonReader reader, object target, JsonObjectContract contract, string memberName)
|
||||
{
|
||||
JsonProperty property;
|
||||
@@ -388,19 +408,19 @@ namespace Newtonsoft.Json.Serialization
|
||||
return;
|
||||
}
|
||||
|
||||
// get the member's underlying type
|
||||
Type memberType = ReflectionUtils.GetMemberUnderlyingType(property.Member);
|
||||
|
||||
object currentValue = null;
|
||||
bool useExistingValue = false;
|
||||
|
||||
if ((Serializer.ObjectCreationHandling == ObjectCreationHandling.Auto || Serializer.ObjectCreationHandling == ObjectCreationHandling.Reuse)
|
||||
ObjectCreationHandling objectCreationHandling =
|
||||
property.ObjectCreationHandling.GetValueOrDefault(Serializer.ObjectCreationHandling);
|
||||
|
||||
if ((objectCreationHandling == ObjectCreationHandling.Auto || objectCreationHandling == ObjectCreationHandling.Reuse)
|
||||
&& (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject)
|
||||
&& property.Readable)
|
||||
{
|
||||
currentValue = ReflectionUtils.GetMemberValue(property.Member, target);
|
||||
currentValue = property.ValueProvider.GetValue(target);
|
||||
|
||||
useExistingValue = (currentValue != null && !memberType.IsArray && !ReflectionUtils.InheritsGenericDefinition(memberType, typeof(ReadOnlyCollection<>)));
|
||||
useExistingValue = (currentValue != null && !property.PropertyType.IsArray && !ReflectionUtils.InheritsGenericDefinition(property.PropertyType, typeof(ReadOnlyCollection<>)));
|
||||
}
|
||||
|
||||
if (!property.Writable && !useExistingValue)
|
||||
@@ -409,10 +429,10 @@ namespace Newtonsoft.Json.Serialization
|
||||
return;
|
||||
}
|
||||
|
||||
object value = CreateValue(reader, memberType, (useExistingValue) ? currentValue : null, JsonTypeReflector.GetConverter(property.Member, memberType));
|
||||
object value = CreateValue(reader, property.PropertyType, (useExistingValue) ? currentValue : null, property.Converter);
|
||||
|
||||
if (!useExistingValue && ShouldSetPropertyValue(property, value))
|
||||
ReflectionUtils.SetMemberValue(property.Member, target, value);
|
||||
property.ValueProvider.SetValue(target, value);
|
||||
}
|
||||
|
||||
private bool ShouldSetPropertyValue(JsonProperty property, object value)
|
||||
@@ -431,7 +451,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
private object CreateAndPopulateDictionary(JsonReader reader, JsonDictionaryContract contract, string id)
|
||||
{
|
||||
IWrappedDictionary dictionary = contract.CreateWrapper(contract.DefaultContstructor.Invoke(null));
|
||||
IWrappedDictionary dictionary = contract.CreateWrapper(contract.DefaultCreator());
|
||||
|
||||
PopulateDictionary(dictionary, reader, contract, id);
|
||||
|
||||
@@ -486,7 +506,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (reference != null && isTemporaryListReference)
|
||||
throw new JsonSerializationException("Cannot preserve reference to array or readonly list: {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
|
||||
#if !PocketPC && !SILVERLIGHT
|
||||
#if !PocketPC
|
||||
if (contract.OnSerializing != null && isTemporaryListReference)
|
||||
throw new JsonSerializationException("Cannot call OnSerializing on an array or readonly list: {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
|
||||
#endif
|
||||
@@ -541,16 +561,19 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
private object CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, string id)
|
||||
{
|
||||
object newObject;
|
||||
object newObject = null;
|
||||
|
||||
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.DefaultContstructor != null &&
|
||||
(contract.DefaultContstructor.IsPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
|
||||
if (contract.DefaultCreator != null &&
|
||||
(!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
|
||||
{
|
||||
newObject = contract.DefaultContstructor.Invoke(null);
|
||||
newObject = contract.DefaultCreator();
|
||||
}
|
||||
|
||||
if (newObject != null)
|
||||
{
|
||||
PopulateObject(newObject, reader, contract, id);
|
||||
return newObject;
|
||||
}
|
||||
@@ -585,8 +608,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
if (!property.Ignored)
|
||||
{
|
||||
Type memberType = ReflectionUtils.GetMemberUnderlyingType(property.Member);
|
||||
propertyValues[property] = CreateValue(reader, memberType, null, property.MemberConverter);
|
||||
propertyValues[property] = CreateValue(reader, property.PropertyType, null, property.MemberConverter);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -627,8 +649,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
// go through unused values and set the newly created object's properties
|
||||
foreach (KeyValuePair<JsonProperty, object> remainingPropertyValue in remainingPropertyValues)
|
||||
{
|
||||
JsonProperty property = remainingPropertyValue.Key;
|
||||
object value = remainingPropertyValue.Value;
|
||||
|
||||
if (ShouldSetPropertyValue(remainingPropertyValue.Key, remainingPropertyValue.Value))
|
||||
ReflectionUtils.SetMemberValue(remainingPropertyValue.Key.Member, createdObject, remainingPropertyValue.Value);
|
||||
property.ValueProvider.SetValue(createdObject, value);
|
||||
}
|
||||
|
||||
contract.InvokeOnDeserialized(createdObject);
|
||||
@@ -639,8 +664,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
contract.InvokeOnDeserializing(newObject);
|
||||
|
||||
Dictionary<string, bool> requiredProperties =
|
||||
contract.Properties.Where(m => m.Required).ToDictionary(m => m.PropertyName, m => false);
|
||||
Dictionary<JsonProperty, RequiredValue> requiredProperties =
|
||||
contract.Properties.Where(m => m.Required != Required.Default).ToDictionary(m => m, m => RequiredValue.None);
|
||||
|
||||
if (id != null)
|
||||
Serializer.ReferenceResolver.AddReference(id, newObject);
|
||||
@@ -657,8 +682,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (!reader.Read())
|
||||
throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
|
||||
|
||||
// set required property even if null (matches WCF IsRequired behavour)
|
||||
SetRequiredProperty(memberName, requiredProperties);
|
||||
SetRequiredProperty(reader, memberName, contract, requiredProperties);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -673,10 +697,12 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
break;
|
||||
case JsonToken.EndObject:
|
||||
foreach (KeyValuePair<string, bool> requiredProperty in requiredProperties)
|
||||
foreach (KeyValuePair<JsonProperty, RequiredValue> requiredProperty in requiredProperties)
|
||||
{
|
||||
if (!requiredProperty.Value)
|
||||
throw new JsonSerializationException("Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, requiredProperty.Key));
|
||||
if (requiredProperty.Value == RequiredValue.None)
|
||||
throw new JsonSerializationException("Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, requiredProperty.Key.PropertyName));
|
||||
if (requiredProperty.Key.Required == Required.Always && requiredProperty.Value == RequiredValue.Null)
|
||||
throw new JsonSerializationException("Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, requiredProperty.Key.PropertyName));
|
||||
}
|
||||
|
||||
contract.InvokeOnDeserialized(newObject);
|
||||
@@ -692,24 +718,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
throw new JsonSerializationException("Unexpected end when deserializing object.");
|
||||
}
|
||||
|
||||
private void SetRequiredProperty(string memberName, Dictionary<string, bool> requiredProperties)
|
||||
private void SetRequiredProperty(JsonReader reader, string memberName, JsonObjectContract contract, Dictionary<JsonProperty, RequiredValue> requiredProperties)
|
||||
{
|
||||
// first attempt to find exact case match
|
||||
// then attempt case insensitive match
|
||||
if (requiredProperties.ContainsKey(memberName))
|
||||
JsonProperty property = requiredProperties.Keys.ForgivingCaseSensitiveFind(p => p.PropertyName, memberName);
|
||||
if (property != null)
|
||||
{
|
||||
requiredProperties[memberName] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (KeyValuePair<string, bool> requiredProperty in requiredProperties)
|
||||
{
|
||||
if (string.Compare(requiredProperty.Key, requiredProperty.Key, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
requiredProperties[requiredProperty.Key] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
requiredProperties[property] = (reader.TokenType == JsonToken.Null || reader.TokenType == JsonToken.Undefined)
|
||||
? RequiredValue.Null
|
||||
: RequiredValue.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,5 +740,12 @@ namespace Newtonsoft.Json.Serialization
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
internal enum RequiredValue
|
||||
{
|
||||
None,
|
||||
Null,
|
||||
Value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,34 +168,32 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
private void WriteMemberInfoProperty(JsonWriter writer, object value, JsonProperty property)
|
||||
{
|
||||
MemberInfo member = property.Member;
|
||||
string propertyName = property.PropertyName;
|
||||
JsonConverter memberConverter = property.MemberConverter;
|
||||
object defaultValue = property.DefaultValue;
|
||||
|
||||
if (!ReflectionUtils.IsIndexedProperty(member))
|
||||
object memberValue = property.ValueProvider.GetValue(value);
|
||||
|
||||
if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore &&
|
||||
memberValue == null)
|
||||
return;
|
||||
|
||||
if (property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling) ==
|
||||
DefaultValueHandling.Ignore && Equals(memberValue, defaultValue))
|
||||
return;
|
||||
|
||||
if (ShouldWriteReference(memberValue, property))
|
||||
{
|
||||
object memberValue = ReflectionUtils.GetMemberValue(member, value);
|
||||
|
||||
if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && memberValue == null)
|
||||
return;
|
||||
|
||||
if (property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling) == DefaultValueHandling.Ignore && Equals(memberValue, defaultValue))
|
||||
return;
|
||||
|
||||
if (ShouldWriteReference(memberValue, property))
|
||||
{
|
||||
writer.WritePropertyName(propertyName ?? member.Name);
|
||||
WriteReference(writer, memberValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckForCircularReference(memberValue, property.ReferenceLoopHandling))
|
||||
return;
|
||||
|
||||
writer.WritePropertyName(propertyName ?? member.Name);
|
||||
SerializeValue(writer, memberValue, memberConverter);
|
||||
writer.WritePropertyName(propertyName);
|
||||
WriteReference(writer, memberValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckForCircularReference(memberValue, property.ReferenceLoopHandling))
|
||||
return;
|
||||
|
||||
writer.WritePropertyName(propertyName);
|
||||
SerializeValue(writer, memberValue, memberConverter);
|
||||
}
|
||||
|
||||
private bool CheckForCircularReference(object value, ReferenceLoopHandling? referenceLoopHandling)
|
||||
@@ -260,10 +258,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
if (TryConvertToString(value, contract.UnderlyingType, out s))
|
||||
{
|
||||
writer.WriteValue(s);
|
||||
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
contract.InvokeOnSerialized(value);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -292,7 +288,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (IsErrorHandled(value, contract, property.Member.Name, ex))
|
||||
if (IsErrorHandled(value, contract, property.PropertyName, ex))
|
||||
HandleError(writer, initialDepth);
|
||||
else
|
||||
throw;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
public class ReflectionValueProvider : IValueProvider
|
||||
{
|
||||
private readonly MemberInfo _memberInfo;
|
||||
|
||||
public ReflectionValueProvider(MemberInfo memberInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo");
|
||||
_memberInfo = memberInfo;
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
ReflectionUtils.SetMemberValue(_memberInfo, target, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public object GetValue(object target)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ReflectionUtils.GetMemberValue(_memberInfo, target);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#if PocketPC || SILVERLIGHT
|
||||
#if PocketPC
|
||||
#pragma warning disable 1591
|
||||
|
||||
// This class is... borrowed from .NET and Microsoft for a short time.
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
#if !SILVERLIGHT && !PocketPC
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Resources;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
public class DynamicWrapperBase
|
||||
{
|
||||
internal protected object UnderlyingObject;
|
||||
}
|
||||
|
||||
public static class DynamicWrapper
|
||||
{
|
||||
private static readonly object _lock = new object();
|
||||
private static readonly WrapperDictionary _wrapperDictionary = new WrapperDictionary();
|
||||
|
||||
private static ModuleBuilder _moduleBuilder;
|
||||
|
||||
private static ModuleBuilder ModuleBuilder
|
||||
{
|
||||
get
|
||||
{
|
||||
Init();
|
||||
return _moduleBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
if (_moduleBuilder == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_moduleBuilder == null)
|
||||
{
|
||||
AssemblyName assemblyName = new AssemblyName("Newtonsoft.Json.Dynamic");
|
||||
assemblyName.KeyPair = new StrongNameKeyPair(GetStrongKey());
|
||||
|
||||
AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
|
||||
_moduleBuilder = assembly.DefineDynamicModule("Newtonsoft.Json.DynamicModule", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] GetStrongKey()
|
||||
{
|
||||
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Newtonsoft.Json.Dynamic.snk"))
|
||||
{
|
||||
if (stream == null)
|
||||
throw new MissingManifestResourceException("Should have a Newtonsoft.Json.Dynamic.snk as an embedded resource.");
|
||||
|
||||
int length = (int)stream.Length;
|
||||
byte[] buffer = new byte[length];
|
||||
stream.Read(buffer, 0, length);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public static Type GetWrapper(Type interfaceType, Type realObjectType)
|
||||
{
|
||||
Type wrapperType = _wrapperDictionary.GetType(interfaceType, realObjectType);
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
wrapperType = GenerateWrapperType(interfaceType, realObjectType);
|
||||
_wrapperDictionary.SetType(interfaceType, realObjectType, wrapperType);
|
||||
}
|
||||
|
||||
return wrapperType;
|
||||
}
|
||||
|
||||
public static object GetUnderlyingObject(object wrapper)
|
||||
{
|
||||
DynamicWrapperBase wrapperBase = wrapper as DynamicWrapperBase;
|
||||
if (wrapperBase == null)
|
||||
throw new ArgumentException("Object is not a wrapper.", "wrapper");
|
||||
|
||||
return wrapperBase.UnderlyingObject;
|
||||
}
|
||||
|
||||
private static Type GenerateWrapperType(Type interfaceType, Type underlyingType)
|
||||
{
|
||||
TypeBuilder wrapperBuilder = ModuleBuilder.DefineType(
|
||||
"{0}_{1}_Wrapper".FormatWith(CultureInfo.InvariantCulture, interfaceType.Name, underlyingType.Name),
|
||||
TypeAttributes.NotPublic | TypeAttributes.Sealed,
|
||||
typeof(DynamicWrapperBase),
|
||||
new[] { interfaceType });
|
||||
|
||||
WrapperMethodBuilder wrapperMethod = new WrapperMethodBuilder(underlyingType, wrapperBuilder);
|
||||
|
||||
foreach (MethodInfo method in interfaceType.AllMethods())
|
||||
{
|
||||
wrapperMethod.Generate(method);
|
||||
}
|
||||
|
||||
return wrapperBuilder.CreateType();
|
||||
}
|
||||
|
||||
public static T CreateWrapper<T>(object realObject) where T : class
|
||||
{
|
||||
var dynamicType = GetWrapper(typeof(T), realObject.GetType());
|
||||
var dynamicWrapper = (DynamicWrapperBase)Activator.CreateInstance(dynamicType);
|
||||
|
||||
dynamicWrapper.UnderlyingObject = realObject;
|
||||
|
||||
return dynamicWrapper as T;
|
||||
}
|
||||
}
|
||||
|
||||
internal class WrapperMethodBuilder
|
||||
{
|
||||
private readonly Type _realObjectType;
|
||||
private readonly TypeBuilder _wrapperBuilder;
|
||||
|
||||
public WrapperMethodBuilder(Type realObjectType, TypeBuilder proxyBuilder)
|
||||
{
|
||||
_realObjectType = realObjectType;
|
||||
_wrapperBuilder = proxyBuilder;
|
||||
}
|
||||
|
||||
public void Generate(MethodInfo newMethod)
|
||||
{
|
||||
if (newMethod.IsGenericMethod)
|
||||
newMethod = newMethod.GetGenericMethodDefinition();
|
||||
|
||||
FieldInfo srcField = typeof(DynamicWrapperBase).GetField("UnderlyingObject", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
|
||||
var parameters = newMethod.GetParameters();
|
||||
var parameterTypes = parameters.Select(parameter => parameter.ParameterType).ToArray();
|
||||
|
||||
MethodBuilder methodBuilder = _wrapperBuilder.DefineMethod(
|
||||
newMethod.Name,
|
||||
MethodAttributes.Public | MethodAttributes.Virtual,
|
||||
newMethod.ReturnType,
|
||||
parameterTypes);
|
||||
|
||||
if (newMethod.IsGenericMethod)
|
||||
{
|
||||
methodBuilder.DefineGenericParameters(
|
||||
newMethod.GetGenericArguments().Select(arg => arg.Name).ToArray());
|
||||
}
|
||||
|
||||
ILGenerator ilGenerator = methodBuilder.GetILGenerator();
|
||||
|
||||
LoadUnderlyingObject(ilGenerator, srcField);
|
||||
PushParameters(parameters, ilGenerator);
|
||||
ExecuteMethod(newMethod, parameterTypes, ilGenerator);
|
||||
Return(ilGenerator);
|
||||
}
|
||||
|
||||
private static void Return(ILGenerator ilGenerator)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
private void ExecuteMethod(MethodBase newMethod, Type[] parameterTypes, ILGenerator ilGenerator)
|
||||
{
|
||||
MethodInfo srcMethod = GetMethod(newMethod, parameterTypes);
|
||||
|
||||
if (srcMethod == null)
|
||||
throw new MissingMethodException("Unable to find method " + newMethod.Name + " on " + _realObjectType.FullName);
|
||||
|
||||
ilGenerator.Emit(OpCodes.Call, srcMethod);
|
||||
}
|
||||
|
||||
private MethodInfo GetMethod(MethodBase realMethod, Type[] parameterTypes)
|
||||
{
|
||||
if (realMethod.IsGenericMethod)
|
||||
return _realObjectType.GetGenericMethod(realMethod.Name, parameterTypes);
|
||||
|
||||
return _realObjectType.GetMethod(realMethod.Name, parameterTypes);
|
||||
}
|
||||
|
||||
private static void PushParameters(ICollection<ParameterInfo> parameters, ILGenerator ilGenerator)
|
||||
{
|
||||
for (int i = 1; i < parameters.Count + 1; i++)
|
||||
ilGenerator.Emit(OpCodes.Ldarg, i);
|
||||
}
|
||||
|
||||
private static void LoadUnderlyingObject(ILGenerator ilGenerator, FieldInfo srcField)
|
||||
{
|
||||
ilGenerator.Emit(OpCodes.Ldarg_0);
|
||||
ilGenerator.Emit(OpCodes.Ldfld, srcField);
|
||||
}
|
||||
}
|
||||
|
||||
internal class WrapperDictionary
|
||||
{
|
||||
private readonly Dictionary<string, Type> _wrapperTypes = new Dictionary<string, Type>();
|
||||
|
||||
private static string GenerateKey(Type interfaceType, Type realObjectType)
|
||||
{
|
||||
return interfaceType.Name + "_" + realObjectType.Name;
|
||||
}
|
||||
|
||||
public Type GetType(Type interfaceType, Type realObjectType)
|
||||
{
|
||||
string key = GenerateKey(interfaceType, realObjectType);
|
||||
|
||||
if (_wrapperTypes.ContainsKey(key))
|
||||
return _wrapperTypes[key];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetType(Type interfaceType, Type realObjectType, Type wrapperType)
|
||||
{
|
||||
string key = GenerateKey(interfaceType, realObjectType);
|
||||
|
||||
if (_wrapperTypes.ContainsKey(key))
|
||||
_wrapperTypes[key] = wrapperType;
|
||||
else
|
||||
_wrapperTypes.Add(key, wrapperType);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TypeExtensions
|
||||
{
|
||||
public static MethodInfo GetGenericMethod(this Type type, string name, params Type[] parameterTypes)
|
||||
{
|
||||
var methods = type.GetMethods().Where(method => method.Name == name);
|
||||
|
||||
foreach (var method in methods)
|
||||
{
|
||||
if (method.HasParameters(parameterTypes))
|
||||
return method;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool HasParameters(this MethodInfo method, params Type[] parameterTypes)
|
||||
{
|
||||
var methodParameters = method.GetParameters().Select(parameter => parameter.ParameterType).ToArray();
|
||||
|
||||
if (methodParameters.Length != parameterTypes.Length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < methodParameters.Length; i++)
|
||||
if (methodParameters[i].ToString() != parameterTypes[i].ToString())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> AllInterfaces(this Type target)
|
||||
{
|
||||
foreach (var IF in target.GetInterfaces())
|
||||
{
|
||||
yield return IF;
|
||||
foreach (var childIF in IF.AllInterfaces())
|
||||
{
|
||||
yield return childIF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<MethodInfo> AllMethods(this Type target)
|
||||
{
|
||||
var allTypes = target.AllInterfaces().ToList();
|
||||
allTypes.Add(target);
|
||||
|
||||
return from type in allTypes
|
||||
from method in type.GetMethods()
|
||||
select method;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,231 @@
|
||||
#if !PocketPC
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class LateBoundDelegateFactory
|
||||
{
|
||||
public static Func<T, object> CreateGet<T>(MemberInfo memberInfo)
|
||||
{
|
||||
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
|
||||
if (propertyInfo != null)
|
||||
return CreateGet<T>(propertyInfo);
|
||||
|
||||
FieldInfo fieldInfo = memberInfo as FieldInfo;
|
||||
if (fieldInfo != null)
|
||||
return CreateGet<T>(fieldInfo);
|
||||
|
||||
throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
|
||||
}
|
||||
|
||||
private static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)
|
||||
{
|
||||
DynamicMethod dynamicMethod = !owner.IsInterface
|
||||
? new DynamicMethod(name, returnType, parameterTypes, owner, true)
|
||||
: new DynamicMethod(name, returnType, parameterTypes, (Module)null, true);
|
||||
|
||||
return dynamicMethod;
|
||||
}
|
||||
|
||||
public static Action<T, object> CreateSet<T>(MemberInfo memberInfo)
|
||||
{
|
||||
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
|
||||
if (propertyInfo != null)
|
||||
return CreateSet<T>(propertyInfo);
|
||||
|
||||
FieldInfo fieldInfo = memberInfo as FieldInfo;
|
||||
if (fieldInfo != null)
|
||||
return CreateSet<T>(fieldInfo);
|
||||
|
||||
throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
|
||||
}
|
||||
|
||||
public static MemberHandler<object> CreateMethodHandler(MethodBase method)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
ParameterInfo[] args = method.GetParameters();
|
||||
|
||||
Label argsOk = generator.DefineLabel();
|
||||
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
generator.Emit(OpCodes.Ldlen);
|
||||
generator.Emit(OpCodes.Ldc_I4, args.Length);
|
||||
generator.Emit(OpCodes.Beq, argsOk);
|
||||
|
||||
generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(Type.EmptyTypes));
|
||||
generator.Emit(OpCodes.Throw);
|
||||
|
||||
generator.MarkLabel(argsOk);
|
||||
|
||||
if (!method.IsConstructor)
|
||||
generator.PushInstance(method.DeclaringType);
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
generator.Emit(OpCodes.Ldc_I4, i);
|
||||
generator.Emit(OpCodes.Ldelem_Ref);
|
||||
|
||||
generator.UnboxIfNeeded(args[i].ParameterType);
|
||||
}
|
||||
|
||||
if (method.IsConstructor)
|
||||
generator.Emit(OpCodes.Newobj, (ConstructorInfo)method);
|
||||
else if (method.IsFinal || !method.IsVirtual)
|
||||
generator.Emit(OpCodes.Call, (MethodInfo)method);
|
||||
else
|
||||
generator.Emit(OpCodes.Callvirt, (MethodInfo)method);
|
||||
|
||||
Type returnType = method.IsConstructor
|
||||
? method.DeclaringType
|
||||
: ((MethodInfo)method).ReturnType;
|
||||
|
||||
if (returnType != typeof(void))
|
||||
generator.BoxIfNeeded(returnType);
|
||||
else
|
||||
generator.Emit(OpCodes.Ldnull);
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return (MemberHandler<object>)dynamicMethod.CreateDelegate(typeof(MemberHandler<object>));
|
||||
}
|
||||
|
||||
|
||||
public static Func<object> CreateDefaultConstructor(Type type)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(object), Type.EmptyTypes, type);
|
||||
dynamicMethod.InitLocals = true;
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
if (type.IsValueType)
|
||||
{
|
||||
generator.DeclareLocal(type);
|
||||
generator.Emit(OpCodes.Ldloc_0);
|
||||
generator.Emit(OpCodes.Box, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstructorInfo constructorInfo =
|
||||
type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null,
|
||||
Type.EmptyTypes, null);
|
||||
|
||||
if (constructorInfo == null)
|
||||
throw new Exception("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type));
|
||||
|
||||
generator.Emit(OpCodes.Newobj, constructorInfo);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return (Func<object>)dynamicMethod.CreateDelegate(typeof(Func<object>));
|
||||
}
|
||||
|
||||
public static Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
MethodInfo getMethod = propertyInfo.GetGetMethod(true);
|
||||
if (getMethod == null)
|
||||
throw new Exception("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture,
|
||||
propertyInfo.Name));
|
||||
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(T), new[] { typeof(object) }, propertyInfo.DeclaringType);
|
||||
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
if (!getMethod.IsStatic)
|
||||
generator.PushInstance(propertyInfo.DeclaringType);
|
||||
|
||||
if (getMethod.IsFinal || !getMethod.IsVirtual)
|
||||
generator.Emit(OpCodes.Call, getMethod);
|
||||
else
|
||||
generator.Emit(OpCodes.Callvirt, getMethod);
|
||||
|
||||
generator.BoxIfNeeded(propertyInfo.PropertyType);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
|
||||
}
|
||||
|
||||
static void PushInstance(this ILGenerator generator, Type type)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
if (type.IsValueType)
|
||||
generator.Emit(OpCodes.Unbox, type);
|
||||
}
|
||||
|
||||
static void BoxIfNeeded(this ILGenerator generator, Type type)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
generator.Emit(OpCodes.Box, type);
|
||||
}
|
||||
|
||||
static void UnboxIfNeeded(this ILGenerator generator, Type type)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
generator.Emit(OpCodes.Unbox_Any, type);
|
||||
}
|
||||
|
||||
public static Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType);
|
||||
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
if (!fieldInfo.IsStatic)
|
||||
generator.PushInstance(fieldInfo.DeclaringType);
|
||||
|
||||
generator.Emit(OpCodes.Ldfld, fieldInfo);
|
||||
generator.BoxIfNeeded(fieldInfo.FieldType);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return (Func<T, object>)
|
||||
dynamicMethod.CreateDelegate(typeof(Func<T, object>));
|
||||
}
|
||||
|
||||
public static Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(object), typeof(object) }, fieldInfo.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
if (!fieldInfo.IsStatic)
|
||||
generator.PushInstance(fieldInfo.DeclaringType);
|
||||
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
generator.UnboxIfNeeded(fieldInfo.FieldType);
|
||||
generator.Emit(OpCodes.Stfld, fieldInfo);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
|
||||
}
|
||||
|
||||
public static Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
MethodInfo getMethod = propertyInfo.GetSetMethod(true);
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(object), typeof(object) }, propertyInfo.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
if (!getMethod.IsStatic)
|
||||
generator.PushInstance(propertyInfo.DeclaringType);
|
||||
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
generator.UnboxIfNeeded(propertyInfo.PropertyType);
|
||||
|
||||
if (getMethod.IsFinal || !getMethod.IsVirtual)
|
||||
generator.Emit(OpCodes.Call, getMethod);
|
||||
else
|
||||
generator.Emit(OpCodes.Callvirt, getMethod);
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -34,6 +34,8 @@ using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal delegate object MemberHandler<T>(T target, params object[] args);
|
||||
|
||||
internal static class ReflectionUtils
|
||||
{
|
||||
public static Type GetObjectType(object v)
|
||||
@@ -76,7 +78,10 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic)
|
||||
{
|
||||
BindingFlags accessModifier = (!nonPublic) ? BindingFlags.Public : BindingFlags.NonPublic;
|
||||
BindingFlags accessModifier = BindingFlags.Public;
|
||||
|
||||
if (nonPublic)
|
||||
accessModifier = accessModifier | BindingFlags.NonPublic;
|
||||
|
||||
return t.GetConstructor(accessModifier | BindingFlags.Instance, null, new Type[0], null);
|
||||
}
|
||||
@@ -187,7 +192,40 @@ namespace Newtonsoft.Json.Utilities
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static bool AssignableToTypeName(this Type type, string fullTypeName, out Type match)
|
||||
{
|
||||
Type current = type;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
if (current.FullName == fullTypeName)
|
||||
{
|
||||
match = current;
|
||||
return true;
|
||||
}
|
||||
|
||||
current = current.BaseType;
|
||||
}
|
||||
|
||||
foreach (Type i in type.GetInterfaces())
|
||||
{
|
||||
if (i.Name == fullTypeName)
|
||||
{
|
||||
match = type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
match = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AssignableToTypeName(this Type type, string fullTypeName)
|
||||
{
|
||||
Type match;
|
||||
return type.AssignableToTypeName(fullTypeName, out match);
|
||||
}
|
||||
|
||||
public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition)
|
||||
{
|
||||
Type implementingType;
|
||||
@@ -361,7 +399,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
case MemberTypes.Event:
|
||||
return ((EventInfo)member).EventHandlerType;
|
||||
default:
|
||||
throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", "member");
|
||||
throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or EventInfo", "member");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,7 +521,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
return true;
|
||||
return !((FieldInfo)member).IsInitOnly;
|
||||
case MemberTypes.Property:
|
||||
return ((PropertyInfo)member).CanWrite;
|
||||
default:
|
||||
@@ -615,6 +653,9 @@ namespace Newtonsoft.Json.Utilities
|
||||
#if !PocketPC
|
||||
return Activator.CreateInstance(type, args);
|
||||
#else
|
||||
if (type.IsValueType)
|
||||
return Activator.CreateInstance(type);
|
||||
|
||||
ConstructorInfo[] constructors = type.GetConstructors();
|
||||
ConstructorInfo match = constructors.Where(c =>
|
||||
{
|
||||
@@ -635,7 +676,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
}).FirstOrDefault();
|
||||
|
||||
if (match == null)
|
||||
throw new Exception("Could not create '{0}' with given parameters.".FormatWith(CultureInfo.InvariantCulture, args));
|
||||
throw new Exception("Could not create '{0}' with given parameters.".FormatWith(CultureInfo.InvariantCulture, type));
|
||||
|
||||
return match.Invoke(args);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user