-Added JsonDictionaryAttribute

-Added JsonContainerContract
-Added support for customizing the JsonConverter, type name handling, reference handling of collection items
This commit is contained in:
James Newton-King
2012-04-22 23:17:58 +12:00
parent 450996eb25
commit 7b776e9298
34 changed files with 894 additions and 252 deletions
@@ -25,6 +25,7 @@
using System;
#if !NETFX_CORE
using System.Collections.Generic;
using NUnit.Framework;
#else
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -32,6 +33,7 @@ using TestFixture = Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttrib
using Test = Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute;
#endif
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Tests.Serialization;
using Newtonsoft.Json.Tests.TestObjects;
namespace Newtonsoft.Json.Tests.Converters
@@ -129,5 +131,118 @@ namespace Newtonsoft.Json.Tests.Converters
DateTime result = JsonConvert.DeserializeObject<DateTime>("new Date(976918263055)", converter);
Assert.AreEqual(new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Utc), result);
}
[Test]
public void ConverterList()
{
ConverterList<object> l1 = new ConverterList<object>();
l1.Add(new DateTime(2000, 12, 12, 20, 10, 0, DateTimeKind.Utc));
l1.Add(new DateTime(1983, 10, 9, 23, 10, 0, DateTimeKind.Utc));
string json = JsonConvert.SerializeObject(l1, Formatting.Indented);
Assert.AreEqual(@"[
new Date(
976651800000
),
new Date(
434589000000
)
]", json);
ConverterList<object> l2 = JsonConvert.DeserializeObject<ConverterList<object>>(json);
Assert.IsNotNull(l2);
Assert.AreEqual(new DateTime(2000, 12, 12, 20, 10, 0, DateTimeKind.Utc), l2[0]);
Assert.AreEqual(new DateTime(1983, 10, 9, 23, 10, 0, DateTimeKind.Utc), l2[1]);
}
[Test]
public void ConverterDictionary()
{
ConverterDictionary<object> l1 = new ConverterDictionary<object>();
l1.Add("First", new DateTime(2000, 12, 12, 20, 10, 0, DateTimeKind.Utc));
l1.Add("Second", new DateTime(1983, 10, 9, 23, 10, 0, DateTimeKind.Utc));
string json = JsonConvert.SerializeObject(l1, Formatting.Indented);
Assert.AreEqual(@"{
""First"": new Date(
976651800000
),
""Second"": new Date(
434589000000
)
}", json);
ConverterDictionary<object> l2 = JsonConvert.DeserializeObject<ConverterDictionary<object>>(json);
Assert.IsNotNull(l2);
Assert.AreEqual(new DateTime(2000, 12, 12, 20, 10, 0, DateTimeKind.Utc), l2["First"]);
Assert.AreEqual(new DateTime(1983, 10, 9, 23, 10, 0, DateTimeKind.Utc), l2["Second"]);
}
[Test]
public void ConverterObject()
{
ConverterObject l1 = new ConverterObject();
l1.Object1 = new DateTime(2000, 12, 12, 20, 10, 0, DateTimeKind.Utc);
l1.Object2 = null;
l1.ObjectNotHandled = new DateTime(2000, 12, 12, 20, 10, 0, DateTimeKind.Utc);
string json = JsonConvert.SerializeObject(l1, Formatting.Indented);
Assert.AreEqual(@"{
""Object1"": new Date(
976651800000
),
""Object2"": null,
""ObjectNotHandled"": 631122486000000000
}", json);
ConverterObject l2 = JsonConvert.DeserializeObject<ConverterObject>(json);
Assert.IsNotNull(l2);
//Assert.AreEqual(new DateTime(2000, 12, 12, 20, 10, 0, DateTimeKind.Utc), l2["First"]);
//Assert.AreEqual(new DateTime(1983, 10, 9, 23, 10, 0, DateTimeKind.Utc), l2["Second"]);
}
}
[JsonArray(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
public class ConverterList<T> : List<T>
{
}
[JsonDictionary(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
public class ConverterDictionary<T> : Dictionary<string, T>
{
}
[JsonObject(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
public class ConverterObject
{
public object Object1 { get; set; }
public object Object2 { get; set; }
[JsonConverter(typeof(DateIntConverter))]
public object ObjectNotHandled { get; set; }
}
public class DateIntConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DateTime? d = (DateTime?) value;
if (d == null)
writer.WriteNull();
else
writer.WriteValue(d.Value.Ticks);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return new DateTime(Convert.ToInt64(reader.Value), DateTimeKind.Utc);
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof (DateTime) || objectType == typeof (DateTime?);
}
}
}
@@ -75,17 +75,5 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(DefaultValueHandling.Ignore, attribute._defaultValueHandling);
Assert.AreEqual(DefaultValueHandling.Ignore, attribute.DefaultValueHandling);
}
[Test]
public void ReferenceLoopHandlingTest()
{
JsonPropertyAttribute attribute = new JsonPropertyAttribute();
Assert.AreEqual(null, attribute._defaultValueHandling);
Assert.AreEqual(ReferenceLoopHandling.Error, attribute.ReferenceLoopHandling);
attribute.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
Assert.AreEqual(ReferenceLoopHandling.Ignore, attribute._referenceLoopHandling);
Assert.AreEqual(ReferenceLoopHandling.Ignore, attribute.ReferenceLoopHandling);
}
}
}
@@ -50,70 +50,6 @@ namespace Newtonsoft.Json.Tests
[TestFixture]
public class JsonConvertTest : TestFixtureBase
{
#if Entities
[Test]
public void EntitiesTest()
{
Purchase purchase = new Purchase() { Id = 1 };
purchase.PurchaseLine.Add(new PurchaseLine() { Id = 1, Purchase = purchase });
purchase.PurchaseLine.Add(new PurchaseLine() { Id = 2, Purchase = purchase });
StringWriter sw = new StringWriter();
JsonSerializer serializer = new JsonSerializer();
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
using (JsonWriter jw = new JsonTextWriter(sw))
{
jw.Formatting = Formatting.Indented;
serializer.Serialize(jw, purchase);
}
string json = sw.ToString();
Assert.AreEqual(@"{
""Id"": 1,
""PurchaseLine"": [
{
""Id"": 1,
""PurchaseReference"": {
""EntityKey"": null,
""RelationshipName"": ""EntityDataModel.PurchasePurchaseLine"",
""SourceRoleName"": ""PurchaseLine"",
""TargetRoleName"": ""Purchase"",
""RelationshipSet"": null,
""IsLoaded"": false
},
""EntityState"": 1,
""EntityKey"": null
},
{
""Id"": 2,
""PurchaseReference"": {
""EntityKey"": null,
""RelationshipName"": ""EntityDataModel.PurchasePurchaseLine"",
""SourceRoleName"": ""PurchaseLine"",
""TargetRoleName"": ""Purchase"",
""RelationshipSet"": null,
""IsLoaded"": false
},
""EntityState"": 1,
""EntityKey"": null
}
],
""EntityState"": 1,
""EntityKey"": null
}", json);
Purchase newPurchase = JsonConvert.DeserializeObject<Purchase>(json);
Assert.AreEqual(1, newPurchase.Id);
Assert.AreEqual(2, newPurchase.PurchaseLine.Count);
Assert.AreEqual(1, newPurchase.PurchaseLine.ElementAt(0).Id);
Assert.AreEqual(2, newPurchase.PurchaseLine.ElementAt(1).Id);
}
#endif
[Test]
public void DeserializeObject_EmptyString()
{
@@ -93,7 +93,12 @@
<Compile Include="Linq\JPathTests.cs" />
<Compile Include="Linq\JRawTests.cs" />
<Compile Include="Serialization\ConstructorHandlingTests.cs" />
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\JsonPropertyCollectionTests.cs" />
<Compile Include="Serialization\NullValueHandlingTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="TestObjects\Bar.cs" />
<Compile Include="TestObjects\Car.cs" />
@@ -138,7 +138,9 @@
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\JsonPropertyCollectionTests.cs" />
<Compile Include="Serialization\NullValueHandlingTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="TestObjects\Bar.cs" />
<Compile Include="TestObjects\Car.cs" />
@@ -149,8 +151,13 @@
<Compile Include="TestObjects\ContentSubClass.cs" />
<Compile Include="TestObjects\Foo.cs" />
<Compile Include="TestObjects\HolderClass.cs" />
<Compile Include="TestObjects\IPrivateImplementationA.cs" />
<Compile Include="TestObjects\IPrivateImplementationB.cs" />
<Compile Include="TestObjects\IPrivateOverriddenImplementation.cs" />
<Compile Include="TestObjects\ListOfIds.cs" />
<Compile Include="TestObjects\Movie.cs" />
<Compile Include="TestObjects\PrivateImplementationAClass.cs" />
<Compile Include="TestObjects\PrivateImplementationBClass.cs" />
<Compile Include="TestObjects\PublicParametizedConstructorRequiringConverterTestClass.cs" />
<Compile Include="TestObjects\PublicParametizedConstructorTestClass.cs" />
<Compile Include="TestObjects\PersonError.cs" />
@@ -136,6 +136,7 @@
<Compile Include="Serialization\NullValueHandlingTests.cs" />
<Compile Include="Serialization\PopulateTests.cs" />
<Compile Include="Serialization\PreserveReferencesHandlingTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\SerializationErrorHandlingTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
<Compile Include="Serialization\TypeNameHandlingTests.cs" />
@@ -99,6 +99,7 @@
<Compile Include="Serialization\NullValueHandlingTests.cs" />
<Compile Include="Serialization\PopulateTests.cs" />
<Compile Include="Serialization\PreserveReferencesHandlingTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\SerializationErrorHandlingTests.cs" />
<Compile Include="Serialization\SerializationEventAttributeTests.cs" />
<Compile Include="Serialization\TypeNameHandlingTests.cs" />
@@ -144,6 +144,7 @@
<Compile Include="Serialization\ContractResolverTests.cs" />
<Compile Include="Serialization\DefaultValueHandlingTests.cs" />
<Compile Include="Serialization\DynamicTests.cs" />
<Compile Include="Serialization\ReferenceLoopHandlingTests.cs" />
<Compile Include="Serialization\WebApiIntegrationTests.cs" />
<Compile Include="Serialization\JsonPropertyCollectionTests.cs" />
<Compile Include="Serialization\NullValueHandlingTests.cs" />
@@ -72,5 +72,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.5.3.14821")]
[assembly: AssemblyFileVersion("4.5.3.14822")]
#endif
@@ -1,15 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
#if !NETFX_CORE
using System.Runtime.Serialization;
using NUnit.Framework;
#else
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestFixture = Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute;
using Test = Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute;
#endif
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Tests.TestObjects;
using System.Reflection;
@@ -59,16 +62,19 @@ namespace Newtonsoft.Json.Tests.Serialization
}
}
#if !NET20
public class AddressWithDataMember
{
[DataMember(Name = "CustomerAddress1")]
public string AddressLine1 { get; set; }
}
#endif
[TestFixture]
public class ContractResolverTests : TestFixtureBase
{
#if !NET20
[Test]
public void DeserializeDataMemberClassWithNoDataContract()
{
@@ -77,6 +83,7 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual("AddressLine1", contract.Properties[0].PropertyName);
}
#endif
[Test]
public void ResolveProperties_IgnoreStatic()
@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Tests.TestObjects;
#if !NETFX_CORE
using NUnit.Framework;
@@ -1016,7 +1016,7 @@ keyword such as type of business.""
public void IncompatibleJsonAttributeShouldThrow()
{
ExceptionAssert.Throws<JsonSerializationException>(
"JsonConverter IsoDateTimeConverter on Newtonsoft.Json.Tests.TestObjects.IncompatibleJsonAttributeClass is not compatible with member type IncompatibleJsonAttributeClass.",
"Unexpected value when converting date. Expected DateTime or DateTimeOffset, got Newtonsoft.Json.Tests.TestObjects.IncompatibleJsonAttributeClass.",
() =>
{
IncompatibleJsonAttributeClass c = new IncompatibleJsonAttributeClass();
@@ -6193,4 +6193,15 @@ Parameter name: value",
}
}
#endif
[JsonObject(MemberSerialization.OptIn)]
public class TestComponentSimple
{
[JsonProperty]
public int MyProperty { get; set; }
public TestComponentSimple()
{
}
}
}
@@ -24,10 +24,7 @@
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Tests.TestObjects;
#if !NETFX_CORE
using NUnit.Framework;
@@ -42,6 +39,7 @@ namespace Newtonsoft.Json.Tests.Serialization
[TestFixture]
public class NullValueHandlingTests : TestFixtureBase
{
#if !NET20
[Test]
public void DeserializeNullIntoDateTime()
{
@@ -55,6 +53,7 @@ namespace Newtonsoft.Json.Tests.Serialization
DateTimeTestClass c = JsonConvert.DeserializeObject<DateTimeTestClass>(@"{DateTimeField:""""}", new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Assert.AreEqual(c.DateTimeField, default(DateTime));
}
#endif
[Test]
public void NullValueHandlingSerialization()
@@ -884,5 +884,148 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreNotEqual(myClasses1[0], myClasses2[0]);
}
[Test]
public void ReferencedIntList()
{
ReferencedList<int> l = new ReferencedList<int>();
l.Add(1);
l.Add(2);
l.Add(3);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
1,
2,
3
]", json);
}
[Test]
public void ReferencedComponentList()
{
var c1 = new TestComponentSimple();
ReferencedList<TestComponentSimple> l = new ReferencedList<TestComponentSimple>();
l.Add(c1);
l.Add(new TestComponentSimple());
l.Add(c1);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
{
""$id"": ""1"",
""MyProperty"": 0
},
{
""$id"": ""2"",
""MyProperty"": 0
},
{
""$ref"": ""1""
}
]", json);
}
[Test]
public void ReferencedIntDictionary()
{
ReferencedDictionary<int> l = new ReferencedDictionary<int>();
l.Add("First", 1);
l.Add("Second", 2);
l.Add("Third", 3);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"{
""First"": 1,
""Second"": 2,
""Third"": 3
}", json);
}
[Test]
public void ReferencedComponentDictionary()
{
var c1 = new TestComponentSimple();
ReferencedDictionary<TestComponentSimple> l = new ReferencedDictionary<TestComponentSimple>();
l.Add("First", c1);
l.Add("Second", new TestComponentSimple());
l.Add("Third", c1);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"{
""First"": {
""$id"": ""1"",
""MyProperty"": 0
},
""Second"": {
""$id"": ""2"",
""MyProperty"": 0
},
""Third"": {
""$ref"": ""1""
}
}", json);
ReferencedDictionary<TestComponentSimple> d = JsonConvert.DeserializeObject<ReferencedDictionary<TestComponentSimple>>(json);
Assert.AreEqual(3, d.Count);
Assert.IsTrue(ReferenceEquals(d["First"], d["Third"]));
}
[Test]
public void ReferencedObjectItems()
{
ReferenceObject o1 = new ReferenceObject();
o1.Component1 = new TestComponentSimple { MyProperty = 1 };
o1.Component2 = o1.Component1;
o1.ComponentNotReference = new TestComponentSimple();
o1.String = "String!";
o1.Integer = int.MaxValue;
string json = JsonConvert.SerializeObject(o1, Formatting.Indented);
string expected = @"{
""Component1"": {
""$id"": ""1"",
""MyProperty"": 1
},
""Component2"": {
""$ref"": ""1""
},
""ComponentNotReference"": {
""MyProperty"": 0
},
""String"": ""String!"",
""Integer"": 2147483647
}";
Assert.AreEqual(expected, json);
ReferenceObject referenceObject = JsonConvert.DeserializeObject<ReferenceObject>(json);
Assert.IsNotNull(referenceObject);
Assert.IsTrue(ReferenceEquals(referenceObject.Component1, referenceObject.Component2));
}
}
[JsonArray(ItemIsReference = true)]
public class ReferencedList<T> : List<T>
{
}
[JsonDictionary(ItemIsReference = true)]
public class ReferencedDictionary<T> : Dictionary<string, T>
{
}
[JsonObject(ItemIsReference = true)]
public class ReferenceObject
{
public TestComponentSimple Component1 { get; set; }
public TestComponentSimple Component2 { get; set; }
[JsonProperty(IsReference = false)]
public TestComponentSimple ComponentNotReference { get; set; }
public string String { get; set; }
public int Integer { get; set; }
}
}
@@ -0,0 +1,123 @@
using System.Collections.Generic;
using NUnit.Framework;
namespace Newtonsoft.Json.Tests.Serialization
{
[TestFixture]
public class ReferenceLoopHandlingTests : TestFixtureBase
{
[Test]
public void ReferenceLoopHandlingTest()
{
JsonPropertyAttribute attribute = new JsonPropertyAttribute();
Assert.AreEqual(null, attribute._defaultValueHandling);
Assert.AreEqual(ReferenceLoopHandling.Error, attribute.ReferenceLoopHandling);
attribute.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
Assert.AreEqual(ReferenceLoopHandling.Ignore, attribute._referenceLoopHandling);
Assert.AreEqual(ReferenceLoopHandling.Ignore, attribute.ReferenceLoopHandling);
}
[Test]
public void IgnoreObjectReferenceLoop()
{
ReferenceLoopHandlingObjectContainerAttribute o = new ReferenceLoopHandlingObjectContainerAttribute();
o.Value = o;
string json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
});
Assert.AreEqual("{}", json);
}
[Test]
public void IgnoreObjectReferenceLoopWithPropertyOverride()
{
ReferenceLoopHandlingObjectContainerAttributeWithPropertyOverride o = new ReferenceLoopHandlingObjectContainerAttributeWithPropertyOverride();
o.Value = o;
string json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
});
Assert.AreEqual(@"{
""Value"": {
""Value"": {
""Value"": {
""Value"": {
""Value"": {
""Value"": null
}
}
}
}
}
}", json);
}
[Test]
public void IgnoreArrayReferenceLoop()
{
ReferenceLoopHandlingList a = new ReferenceLoopHandlingList();
a.Add(a);
string json = JsonConvert.SerializeObject(a, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
});
Assert.AreEqual("[]", json);
}
[Test]
public void IgnoreDictionaryReferenceLoop()
{
ReferenceLoopHandlingDictionary d = new ReferenceLoopHandlingDictionary();
d.Add("First", d);
string json = JsonConvert.SerializeObject(d, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
});
Assert.AreEqual("{}", json);
}
}
[JsonArray(ItemReferenceLoopHandling = ReferenceLoopHandling.Ignore)]
public class ReferenceLoopHandlingList : List<ReferenceLoopHandlingList>
{
}
[JsonDictionary(ItemReferenceLoopHandling = ReferenceLoopHandling.Ignore)]
public class ReferenceLoopHandlingDictionary : Dictionary<string, ReferenceLoopHandlingDictionary>
{
}
[JsonObject(ItemReferenceLoopHandling = ReferenceLoopHandling.Ignore)]
public class ReferenceLoopHandlingObjectContainerAttribute
{
public ReferenceLoopHandlingObjectContainerAttribute Value { get; set; }
}
[JsonObject(ItemReferenceLoopHandling = ReferenceLoopHandling.Ignore)]
public class ReferenceLoopHandlingObjectContainerAttributeWithPropertyOverride
{
private ReferenceLoopHandlingObjectContainerAttributeWithPropertyOverride _value;
private int _getCount;
[JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Serialize)]
public ReferenceLoopHandlingObjectContainerAttributeWithPropertyOverride Value
{
get
{
if (_getCount < 5)
{
_getCount++;
return _value;
}
return null;
}
set { _value = value; }
}
}
}
@@ -628,7 +628,6 @@ namespace Newtonsoft.Json.Tests.Serialization
testObject.AnotherTestMember[1].Add(new ContentSubClass("Second One"));
testObject.AThirdTestMember = new ContentSubClass("Third One");
JsonSerializer serializingTester = new JsonSerializer();
serializingTester.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
@@ -646,29 +645,27 @@ namespace Newtonsoft.Json.Tests.Serialization
string dictionaryRef = ReflectionUtils.GetTypeName(typeof(Dictionary<int, IList<ContentBaseClass>>), FormatterAssemblyStyle.Simple);
string listRef = ReflectionUtils.GetTypeName(typeof(List<ContentBaseClass>), FormatterAssemblyStyle.Simple);
Assert.AreEqual(@"{
string expected = @"{
""TestMember"": {
""$type"": """ + contentSubClassRef + @""",
""SomeString"": ""First One""
},
""AnotherTestMember"": {
""$type"": """ + dictionaryRef + @""",
""1"": {
""$type"": """ + listRef + @""",
""$values"": [
{
""$type"": """ + contentSubClassRef + @""",
""SomeString"": ""Second One""
}
]
}
""1"": [
{
""$type"": """ + contentSubClassRef + @""",
""SomeString"": ""Second One""
}
]
},
""AThirdTestMember"": {
""$type"": """ + contentSubClassRef + @""",
""SomeString"": ""Third One""
}
}", json);
}";
Assert.AreEqual(expected, json);
Console.WriteLine(json);
StringReader sr = new StringReader(json);
@@ -1013,6 +1010,129 @@ namespace Newtonsoft.Json.Tests.Serialization
}
}
#endif
[Test]
public void TypeNameIntList()
{
TypeNameList<int> l = new TypeNameList<int>();
l.Add(1);
l.Add(2);
l.Add(3);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
1,
2,
3
]", json);
}
[Test]
public void TypeNameComponentList()
{
var c1 = new TestComponentSimple();
TypeNameList<object> l = new TypeNameList<object>();
l.Add(c1);
l.Add(new Employee
{
BirthDate = new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc),
Department = "Department!"
});
l.Add("String!");
l.Add(long.MaxValue);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"[
{
""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"",
""MyProperty"": 0
},
{
""$type"": ""Newtonsoft.Json.Tests.TestObjects.Employee, Newtonsoft.Json.Tests"",
""FirstName"": null,
""LastName"": null,
""BirthDate"": ""2000-12-12T12:12:12Z"",
""Department"": ""Department!"",
""JobTitle"": null
},
""String!"",
9223372036854775807
]", json);
TypeNameList<object> l2 = JsonConvert.DeserializeObject<TypeNameList<object>>(json);
Assert.AreEqual(4, l2.Count);
CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), l2[0]);
CustomAssert.IsInstanceOfType(typeof(Employee), l2[1]);
CustomAssert.IsInstanceOfType(typeof(string), l2[2]);
CustomAssert.IsInstanceOfType(typeof(long), l2[3]);
}
[Test]
public void TypeNameDictionary()
{
TypeNameDictionary<object> l = new TypeNameDictionary<object>();
l.Add("First", new TestComponentSimple { MyProperty = 1 });
l.Add("Second", "String!");
l.Add("Third", long.MaxValue);
string json = JsonConvert.SerializeObject(l, Formatting.Indented);
Assert.AreEqual(@"{
""First"": {
""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"",
""MyProperty"": 1
},
""Second"": ""String!"",
""Third"": 9223372036854775807
}", json);
TypeNameDictionary<object> l2 = JsonConvert.DeserializeObject<TypeNameDictionary<object>>(json);
Assert.AreEqual(3, l2.Count);
CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), l2["First"]);
Assert.AreEqual(1, ((TestComponentSimple)l2["First"]).MyProperty);
CustomAssert.IsInstanceOfType(typeof(string), l2["Second"]);
CustomAssert.IsInstanceOfType(typeof(long), l2["Third"]);
}
[Test]
public void TypeNameObjectItems()
{
TypeNameObject o1 = new TypeNameObject();
o1.Object1 = new TestComponentSimple { MyProperty = 1 };
o1.Object2 = 123;
o1.ObjectNotHandled = new TestComponentSimple { MyProperty = int.MaxValue };
o1.String = "String!";
o1.Integer = int.MaxValue;
string json = JsonConvert.SerializeObject(o1, Formatting.Indented);
string expected = @"{
""Object1"": {
""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"",
""MyProperty"": 1
},
""Object2"": 123,
""ObjectNotHandled"": {
""MyProperty"": 2147483647
},
""String"": ""String!"",
""Integer"": 2147483647
}";
Assert.AreEqual(expected, json);
TypeNameObject o2 = JsonConvert.DeserializeObject<TypeNameObject>(json);
Assert.IsNotNull(o2);
CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), o2.Object1);
Assert.AreEqual(1, ((TestComponentSimple)o2.Object1).MyProperty);
CustomAssert.IsInstanceOfType(typeof(long), o2.Object2);
CustomAssert.IsInstanceOfType(typeof(JObject), o2.ObjectNotHandled);
Assert.AreEqual(@"{
""MyProperty"": 2147483647
}", o2.ObjectNotHandled.ToString());
}
}
public class Message
@@ -1102,4 +1222,25 @@ namespace Newtonsoft.Json.Tests.Serialization
}
}
#endif
[JsonArray(ItemTypeNameHandling = TypeNameHandling.All)]
public class TypeNameList<T> : List<T>
{
}
[JsonDictionary(ItemTypeNameHandling = TypeNameHandling.All)]
public class TypeNameDictionary<T> : Dictionary<string, T>
{
}
[JsonObject(ItemTypeNameHandling = TypeNameHandling.All)]
public class TypeNameObject
{
public object Object1 { get; set; }
public object Object2 { get; set; }
[JsonProperty(TypeNameHandling = TypeNameHandling.None)]
public object ObjectNotHandled { get; set; }
public string String { get; set; }
public int Integer { get; set; }
}
}
@@ -59,7 +59,7 @@ namespace Newtonsoft.Json.Converters
if (reader.TokenType == JsonToken.Null)
{
if (!ReflectionUtils.IsNullableType(objectType))
if (!ReflectionUtils.IsNullable(objectType))
throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
return null;
-58
View File
@@ -35,14 +35,6 @@ namespace Newtonsoft.Json
{
private bool _allowNullItems;
// yuck. can't set nullable properties on an attribute in C#
// have to use this approach to get an unset default state
internal NullValueHandling? _itemNullValueHandling;
internal DefaultValueHandling? _itemDefaultValueHandling;
internal ReferenceLoopHandling? _itemReferenceLoopHandling;
internal ObjectCreationHandling? _itemObjectCreationHandling;
internal TypeNameHandling? _itemTypeNameHandling;
/// <summary>
/// Gets or sets a value indicating whether null items are allowed in the collection.
/// </summary>
@@ -53,56 +45,6 @@ namespace Newtonsoft.Json
set { _allowNullItems = value; }
}
/// <summary>
/// Gets or sets the null value handling used when serializing the collection's items.
/// </summary>
/// <value>The null value handling.</value>
public NullValueHandling ItemNullValueHandling
{
get { return _itemNullValueHandling ?? default(NullValueHandling); }
set { _itemNullValueHandling = value; }
}
/// <summary>
/// Gets or sets the default value handling used when serializing the collection's items.
/// </summary>
/// <value>The default value handling.</value>
public DefaultValueHandling ItemDefaultValueHandling
{
get { return _itemDefaultValueHandling ?? default(DefaultValueHandling); }
set { _itemDefaultValueHandling = value; }
}
/// <summary>
/// Gets or sets the reference loop handling used when serializing the collection's items.
/// </summary>
/// <value>The reference loop handling.</value>
public ReferenceLoopHandling ItemReferenceLoopHandling
{
get { return _itemReferenceLoopHandling ?? default(ReferenceLoopHandling); }
set { _itemReferenceLoopHandling = value; }
}
/// <summary>
/// Gets or sets the object creation handling used when deserializing the collection's items.
/// </summary>
/// <value>The object creation handling.</value>
public ObjectCreationHandling ItemObjectCreationHandling
{
get { return _itemObjectCreationHandling ?? default(ObjectCreationHandling); }
set { _itemObjectCreationHandling = value; }
}
/// <summary>
/// Gets or sets the type name handling used when serializing the collection's items.
/// </summary>
/// <value>The type name handling.</value>
public TypeNameHandling ItemTypeNameHandling
{
get { return _itemTypeNameHandling ?? default(TypeNameHandling); }
set { _itemTypeNameHandling = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonArrayAttribute"/> class.
/// </summary>
+42 -1
View File
@@ -49,12 +49,21 @@ namespace Newtonsoft.Json
/// <value>The description.</value>
public string Description { get; set; }
/// <summary>
/// Gets the collection's items converter.
/// </summary>
/// <value>The collection's items converter.</value>
public Type ItemConverterType { get; set; }
// yuck. can't set nullable properties on an attribute in C#
// have to use this approach to get an unset default state
internal bool? _isReference;
internal bool? _itemIsReference;
internal ReferenceLoopHandling? _itemReferenceLoopHandling;
internal TypeNameHandling? _itemTypeNameHandling;
/// <summary>
/// Gets or sets a value that indicates whether to preserve object reference data.
/// Gets or sets a value that indicates whether to preserve object references.
/// </summary>
/// <value>
/// <c>true</c> to keep object reference; otherwise, <c>false</c>. The default is <c>false</c>.
@@ -65,6 +74,38 @@ namespace Newtonsoft.Json
set { _isReference = value; }
}
/// <summary>
/// Gets or sets a value that indicates whether to preserve collection's items references.
/// </summary>
/// <value>
/// <c>true</c> to keep collection's items object references; otherwise, <c>false</c>. The default is <c>false</c>.
/// </value>
public bool ItemIsReference
{
get { return _itemIsReference ?? default(bool); }
set { _itemIsReference = value; }
}
/// <summary>
/// Gets or sets the reference loop handling used when serializing the collection's items.
/// </summary>
/// <value>The reference loop handling.</value>
public ReferenceLoopHandling ItemReferenceLoopHandling
{
get { return _itemReferenceLoopHandling ?? default(ReferenceLoopHandling); }
set { _itemReferenceLoopHandling = value; }
}
/// <summary>
/// Gets or sets the type name handling used when serializing the collection's items.
/// </summary>
/// <value>The type name handling.</value>
public TypeNameHandling ItemTypeNameHandling
{
get { return _itemTypeNameHandling ?? default(TypeNameHandling); }
set { _itemTypeNameHandling = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonContainerAttribute"/> class.
/// </summary>
@@ -0,0 +1,52 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
namespace Newtonsoft.Json
{
/// <summary>
/// Instructs the <see cref="JsonSerializer"/> how to serialize the collection.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
public sealed class JsonDictionaryAttribute : JsonContainerAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="JsonDictionaryAttribute"/> class.
/// </summary>
public JsonDictionaryAttribute()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonDictionaryAttribute"/> class with the specified container Id.
/// </summary>
/// <param name="id">The container Id.</param>
public JsonDictionaryAttribute(string id)
: base(id)
{
}
}
}
@@ -98,10 +98,12 @@
<Compile Include="FormatterAssemblyStyle.cs" />
<Compile Include="Formatting.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="JsonDictionaryAttribute.cs" />
<Compile Include="JsonException.cs" />
<Compile Include="JsonPosition.cs" />
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
<Compile Include="SerializationBinder.cs" />
<Compile Include="Serialization\JsonContainerContract.cs" />
<Compile Include="StreamingContext.cs" />
<Compile Include="Utilities\LinqBridge.cs" />
<Compile Include="Linq\JPath.cs" />
@@ -110,11 +110,13 @@
<Compile Include="FormatterAssemblyStyle.cs" />
<Compile Include="Formatting.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="JsonDictionaryAttribute.cs" />
<Compile Include="JsonException.cs" />
<Compile Include="JsonPosition.cs" />
<Compile Include="Linq\JPropertyDescriptor.cs" />
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
<Compile Include="SerializationBinder.cs" />
<Compile Include="Serialization\JsonContainerContract.cs" />
<Compile Include="StreamingContext.cs" />
<Compile Include="Utilities\DynamicProxy.cs" />
<Compile Include="Linq\JPath.cs" />
@@ -117,6 +117,7 @@
<Compile Include="JsonConverter.cs" />
<Compile Include="JsonConverterAttribute.cs" />
<Compile Include="JsonConverterCollection.cs" />
<Compile Include="JsonDictionaryAttribute.cs" />
<Compile Include="JsonException.cs" />
<Compile Include="JsonIgnoreAttribute.cs" />
<Compile Include="JsonObjectAttribute.cs" />
@@ -172,6 +173,7 @@
<Compile Include="Serialization\IReferenceResolver.cs" />
<Compile Include="Serialization\IValueProvider.cs" />
<Compile Include="Serialization\JsonArrayContract.cs" />
<Compile Include="Serialization\JsonContainerContract.cs" />
<Compile Include="Serialization\JsonContract.cs" />
<Compile Include="Serialization\JsonDictionaryContract.cs" />
<Compile Include="Serialization\JsonDynamicContract.cs" />
@@ -90,6 +90,7 @@
<Compile Include="JsonConverter.cs" />
<Compile Include="JsonConverterAttribute.cs" />
<Compile Include="JsonConverterCollection.cs" />
<Compile Include="JsonDictionaryAttribute.cs" />
<Compile Include="JsonException.cs" />
<Compile Include="JsonIgnoreAttribute.cs" />
<Compile Include="JsonObjectAttribute.cs" />
@@ -145,6 +146,7 @@
<Compile Include="Serialization\IReferenceResolver.cs" />
<Compile Include="Serialization\IValueProvider.cs" />
<Compile Include="Serialization\JsonArrayContract.cs" />
<Compile Include="Serialization\JsonContainerContract.cs" />
<Compile Include="Serialization\JsonContract.cs" />
<Compile Include="Serialization\JsonDictionaryContract.cs" />
<Compile Include="Serialization\JsonDynamicContract.cs" />
@@ -103,6 +103,7 @@
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="ConstructorHandling.cs" />
<Compile Include="Converters\VersionConverter.cs" />
<Compile Include="JsonDictionaryAttribute.cs" />
<Compile Include="JsonException.cs" />
<Compile Include="DateFormatHandling.cs" />
<Compile Include="DateParseHandling.cs" />
@@ -111,6 +112,7 @@
<Compile Include="JsonConstructorAttribute.cs" />
<Compile Include="JsonPosition.cs" />
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
<Compile Include="Serialization\JsonContainerContract.cs" />
<Compile Include="Utilities\DynamicProxy.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JRaw.cs" />
@@ -91,7 +91,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.5.3.14821")]
[assembly: AssemblyFileVersion("4.5.3.14822")]
#endif
[assembly: CLSCompliant(true)]
@@ -732,6 +732,9 @@ namespace Newtonsoft.Json.Serialization
if (JsonTypeReflector.GetJsonArrayAttribute(t) != null)
return CreateArrayContract(objectType);
if (JsonTypeReflector.GetJsonDictionaryAttribute(t) != null)
return CreateDictionaryContract(objectType);
if (t == typeof(JToken) || t.IsSubclassOf(typeof(JToken)))
return CreateLinqContract(objectType);
@@ -39,7 +39,7 @@ namespace Newtonsoft.Json.Serialization
/// <summary>
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
/// </summary>
public class JsonArrayContract : JsonContract
public class JsonArrayContract : JsonContainerContract
{
/// <summary>
/// Gets the <see cref="Type"/> of the collection items.
@@ -0,0 +1,88 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json.Utilities;
using System.Collections;
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
namespace Newtonsoft.Json.Serialization
{
/// <summary>
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
/// </summary>
public class JsonContainerContract : JsonContract
{
/// <summary>
/// Gets or sets the default collection items <see cref="JsonConverter" />.
/// </summary>
/// <value>The converter.</value>
public JsonConverter ItemConverter { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the collection items preserve object references.
/// </summary>
/// <value><c>true</c> if collection items preserve object references; otherwise, <c>false</c>.</value>
public bool? ItemIsReference { get; set; }
/// <summary>
/// Gets or sets the collection item reference loop handling.
/// </summary>
/// <value>The reference loop handling.</value>
public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; }
/// <summary>
/// Gets or sets the collection item type name handling.
/// </summary>
/// <value>The type name handling.</value>
public TypeNameHandling? ItemTypeNameHandling { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="JsonContainerContract"/> class.
/// </summary>
/// <param name="underlyingType">The underlying type for the contract.</param>
internal JsonContainerContract(Type underlyingType)
: base(underlyingType)
{
JsonContainerAttribute jsonContainerAttribute = JsonTypeReflector.GetJsonContainerAttribute(underlyingType);
if (jsonContainerAttribute != null)
{
if (jsonContainerAttribute.ItemConverterType != null)
ItemConverter = JsonConverterAttribute.CreateJsonConverterInstance(jsonContainerAttribute.ItemConverterType);
ItemIsReference = jsonContainerAttribute._itemIsReference;
ItemReferenceLoopHandling = jsonContainerAttribute._itemReferenceLoopHandling;
ItemTypeNameHandling = jsonContainerAttribute._itemTypeNameHandling;
}
}
}
}
@@ -37,7 +37,7 @@ namespace Newtonsoft.Json.Serialization
/// <summary>
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
/// </summary>
public class JsonDictionaryContract : JsonContract
public class JsonDictionaryContract : JsonContainerContract
{
/// <summary>
/// Gets or sets the property name resolver.
@@ -31,7 +31,7 @@ namespace Newtonsoft.Json.Serialization
/// <summary>
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
/// </summary>
public class JsonObjectContract : JsonContract
public class JsonObjectContract : JsonContainerContract
{
/// <summary>
/// Gets or sets the object member serialization.
@@ -113,7 +113,7 @@ namespace Newtonsoft.Json.Serialization
JsonContract contract = GetContractSafe(objectType);
JsonConverter converter = GetConverter(contract, null);
JsonConverter converter = GetConverter(contract, null, null);
if (reader.TokenType == JsonToken.None && !ReadForType(reader, contract, converter != null, false))
{
@@ -123,7 +123,7 @@ namespace Newtonsoft.Json.Serialization
return null;
}
return CreateValueNonProperty(reader, objectType, contract, converter);
return CreateValueNonProperty(reader, objectType, contract, converter, null);
}
private JsonSerializerProxy GetInternalSerializer()
@@ -186,7 +186,7 @@ namespace Newtonsoft.Json.Serialization
return token;
}
private object CreateValueProperty(JsonReader reader, JsonProperty property, JsonConverter propertyConverter, object target, bool gottenCurrentValue, object currentValue)
private object CreateValueProperty(JsonReader reader, JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, object target, bool gottenCurrentValue, object currentValue)
{
JsonContract contract;
JsonConverter converter;
@@ -204,7 +204,7 @@ namespace Newtonsoft.Json.Serialization
contract = GetContractSafe(currentValue.GetType());
if (contract != property.PropertyContract)
converter = GetConverter(contract, property.MemberConverter);
converter = GetConverter(contract, property.MemberConverter, containerContract);
else
converter = propertyConverter;
}
@@ -219,18 +219,18 @@ namespace Newtonsoft.Json.Serialization
return converter.ReadJson(reader, objectType, currentValue, GetInternalSerializer());
}
return CreateValueInternal(reader, objectType, contract, property, currentValue);
return CreateValueInternal(reader, objectType, contract, property, containerContract, currentValue);
}
private object CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract, JsonConverter converter)
private object CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract, JsonConverter converter, JsonContainerContract containerContract)
{
if (converter != null && converter.CanRead)
return converter.ReadJson(reader, objectType, null, GetInternalSerializer());
return CreateValueInternal(reader, objectType, contract, null, null);
return CreateValueInternal(reader, objectType, contract, null, containerContract, null);
}
private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue)
private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, object existingValue)
{
if (contract != null && contract.ContractType == JsonContractType.Linq)
return CreateJToken(reader, contract);
@@ -242,7 +242,7 @@ namespace Newtonsoft.Json.Serialization
// populate a typed object or generic dictionary/array
// depending upon whether an objectType was supplied
case JsonToken.StartObject:
return CreateObject(reader, objectType, contract, member, existingValue);
return CreateObject(reader, objectType, contract, member, containerContract, existingValue);
case JsonToken.StartArray:
return CreateList(reader, objectType, contract, member, existingValue, null);
case JsonToken.Integer:
@@ -262,7 +262,6 @@ namespace Newtonsoft.Json.Serialization
return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType);
case JsonToken.StartConstructor:
case JsonToken.EndConstructor:
string constructorName = reader.Value.ToString();
return constructorName;
@@ -287,7 +286,7 @@ namespace Newtonsoft.Json.Serialization
throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
}
private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter)
private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract)
{
JsonConverter converter = null;
if (memberConverter != null)
@@ -295,6 +294,10 @@ namespace Newtonsoft.Json.Serialization
// member attribute converter
converter = memberConverter;
}
else if (containerContract != null && containerContract.ItemConverter != null)
{
converter = containerContract.ItemConverter;
}
else if (contract != null)
{
JsonConverter matchingConverter;
@@ -311,7 +314,7 @@ namespace Newtonsoft.Json.Serialization
return converter;
}
private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue)
private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, object existingValue)
{
CheckedRead(reader);
@@ -358,7 +361,11 @@ namespace Newtonsoft.Json.Serialization
CheckedRead(reader);
string qualifiedTypeName = reader.Value.ToString();
if ((((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling) != TypeNameHandling.None)
TypeNameHandling resolvedTypeNameHandling = ((member != null) ? member.TypeNameHandling : null)
?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
?? Serializer.TypeNameHandling;
if (resolvedTypeNameHandling != TypeNameHandling.None)
{
string typeName;
string assemblyName;
@@ -433,7 +440,7 @@ namespace Newtonsoft.Json.Serialization
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
{
CheckedRead(reader);
object value = CreateValueInternal(reader, objectType, primitiveContract, member, existingValue);
object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, existingValue);
CheckedRead(reader);
return value;
@@ -561,7 +568,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For
return value.ToString();
}
private void SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonReader reader, object target)
private void SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonReader reader, object target)
{
if (property.Ignored)
{
@@ -612,7 +619,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For
}
object existingValue = (useExistingValue) ? currentValue : null;
object value = CreateValueProperty(reader, property, propertyConverter, target, gottenCurrentValue, existingValue);
object value = CreateValueProperty(reader, property, propertyConverter, containerContract, target, gottenCurrentValue, existingValue);
// always set the value if useExistingValue is false,
// otherwise also set it if CreateValue returns a new value compared to the currentValue
@@ -696,12 +703,12 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For
if (contract.DictionaryValueContract == null)
contract.DictionaryValueContract = GetContractSafe(contract.DictionaryValueType);
JsonConverter dictionaryValueConverter = GetConverter(contract.DictionaryValueContract, null);
JsonConverter dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.DictionaryValueContract, null, contract);
if (!ReadForType(reader, contract.DictionaryValueContract, dictionaryValueConverter != null, false))
throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
dictionary[keyValue] = CreateValueNonProperty(reader, contract.DictionaryValueType, contract.DictionaryValueContract, dictionaryValueConverter);
dictionary[keyValue] = CreateValueNonProperty(reader, contract.DictionaryValueType, contract.DictionaryValueContract, dictionaryValueConverter, contract);
}
catch (Exception ex)
{
@@ -763,7 +770,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For
int index = 0;
JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType);
JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null);
JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract);
while (true)
{
@@ -780,7 +787,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For
case JsonToken.Comment:
break;
default:
object value = CreateValueNonProperty(reader, contract.CollectionItemType, collectionItemContract, collectionItemConverter);
object value = CreateValueNonProperty(reader, contract.CollectionItemType, collectionItemContract, collectionItemConverter, contract);
wrappedList.Add(value);
break;
@@ -900,18 +907,18 @@ To fix this error either change the environment to be fully trusted, change the
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, null);
SetPropertyValue(property, propertyConverter, reader, newObject);
SetPropertyValue(property, propertyConverter, null, reader, newObject);
}
else
{
Type t = (JsonReader.IsPrimitiveToken(reader.TokenType)) ? reader.ValueType : typeof (IDynamicMetaObjectProvider);
JsonContract dynamicMemberContract = GetContractSafe(t);
JsonConverter dynamicMemberConverter = GetConverter(dynamicMemberContract, null);
JsonConverter dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null);
object value = CreateValueNonProperty(reader, t, dynamicMemberContract, dynamicMemberConverter);
object value = CreateValueNonProperty(reader, t, dynamicMemberContract, dynamicMemberConverter, null);
newObject.TrySetMember(memberName, value);
}
@@ -1075,13 +1082,13 @@ To fix this error either change the environment to be fully trusted, change the
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract);
if (!ReadForType(reader, property.PropertyContract, propertyConverter != null, false))
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
if (!property.Ignored)
propertyValues[property] = CreateValueProperty(reader, property, propertyConverter, null, true, null);
propertyValues[property] = CreateValueProperty(reader, property, propertyConverter, contract, null, true, null);
else
reader.Skip();
}
@@ -1193,14 +1200,14 @@ To fix this error either change the environment to be fully trusted, change the
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract);
if (!ReadForType(reader, property.PropertyContract, propertyConverter != null, false))
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
SetPropertyPresence(reader, property, propertiesPresence);
SetPropertyValue(property, propertyConverter, reader, newObject);
SetPropertyValue(property, propertyConverter, contract, reader, newObject);
}
catch (Exception ex)
{
@@ -58,7 +58,7 @@ namespace Newtonsoft.Json.Serialization
if (jsonWriter == null)
throw new ArgumentNullException("jsonWriter");
SerializeValue(jsonWriter, value, GetContractSafe(value), null, null);
SerializeValue(jsonWriter, value, GetContractSafe(value), null, null, null);
}
private JsonSerializerProxy GetInternalSerializer()
@@ -77,11 +77,11 @@ namespace Newtonsoft.Json.Serialization
return Serializer.ContractResolver.ResolveContract(value.GetType());
}
private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContract collectionValueContract)
private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
if (contract.UnderlyingType == typeof (byte[]))
{
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract);
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, collectionValueContract);
if (includeTypeDetails)
{
writer.WriteStartObject();
@@ -96,53 +96,53 @@ namespace Newtonsoft.Json.Serialization
writer.WriteValue(value);
}
private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContract collectionValueContract)
private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
JsonConverter converter = (member != null) ? member.Converter : null;
if (value == null)
{
writer.WriteNull();
return;
}
if ((converter != null
JsonConverter converter;
if ((((converter = (member != null) ? member.Converter : null) != null)
|| ((converter = (collectionContract != null) ? collectionContract.ItemConverter : null) != null)
|| ((converter = valueContract.Converter) != null)
|| ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
|| ((converter = valueContract.InternalConverter) != null))
&& converter.CanWrite)
{
SerializeConvertable(writer, converter, value, valueContract);
SerializeConvertable(writer, converter, value, valueContract, collectionContract, collectionValueContract);
return;
}
switch (valueContract.ContractType)
{
case JsonContractType.Object:
SerializeObject(writer, value, (JsonObjectContract) valueContract, member, collectionValueContract);
SerializeObject(writer, value, (JsonObjectContract) valueContract, member, collectionContract, collectionValueContract);
break;
case JsonContractType.Array:
JsonArrayContract arrayContract = (JsonArrayContract) valueContract;
SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, collectionValueContract);
SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, collectionContract, collectionValueContract);
break;
case JsonContractType.Primitive:
SerializePrimitive(writer, value, (JsonPrimitiveContract) valueContract, member, collectionValueContract);
SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, collectionContract, collectionValueContract);
break;
case JsonContractType.String:
SerializeString(writer, value, (JsonStringContract) valueContract);
break;
case JsonContractType.Dictionary:
JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionValueContract);
SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionContract, collectionValueContract);
break;
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
case JsonContractType.Dynamic:
SerializeDynamic(writer, (IDynamicMetaObjectProvider) value, (JsonDynamicContract) valueContract, member, collectionValueContract);
SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, collectionContract, collectionValueContract);
break;
#endif
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
case JsonContractType.Serializable:
SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) valueContract, member, collectionValueContract);
SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, collectionContract, collectionValueContract);
break;
#endif
case JsonContractType.Linq:
@@ -151,25 +151,35 @@ namespace Newtonsoft.Json.Serialization
}
}
private bool ShouldWriteReference(object value, JsonProperty property, JsonContract contract)
private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract)
{
if (value == null)
return false;
if (contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
return false;
bool? isReference = null;
// value could be coming from a dictionary or array and not have a property
if (property != null)
isReference = property.IsReference;
if (isReference == null && collectionContract != null)
isReference = collectionContract.ItemIsReference;
if (isReference == null)
isReference = contract.IsReference;
return isReference;
}
private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract)
{
if (value == null)
return false;
if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String)
return false;
bool? isReference = ResolveIsReference(valueContract, property, collectionContract);
if (isReference == null)
{
if (contract.ContractType == JsonContractType.Array)
if (valueContract.ContractType == JsonContractType.Array)
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
else
isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
@@ -181,25 +191,25 @@ namespace Newtonsoft.Json.Serialization
return Serializer.ReferenceResolver.IsReferenced(this, value);
}
private void WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract)
private void WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract, JsonContainerContract collectionContract)
{
string propertyName = property.PropertyName;
if (ShouldWriteReference(memberValue, property, contract))
if (ShouldWriteReference(memberValue, property, contract, collectionContract))
{
writer.WritePropertyName(propertyName);
WriteReference(writer, memberValue);
return;
}
if (!CheckForCircularReference(memberValue, property.ReferenceLoopHandling, contract))
if (!CheckForCircularReference(memberValue, property, contract, collectionContract))
return;
if (memberValue == null && property.Required == Required.Always)
throw new JsonSerializationException("Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
writer.WritePropertyName(propertyName);
SerializeValue(writer, memberValue, contract, property, null);
SerializeValue(writer, memberValue, contract, property, collectionContract, null);
}
private bool ShouldWriteProperty(object memberValue, JsonProperty property)
@@ -215,11 +225,19 @@ namespace Newtonsoft.Json.Serialization
return true;
}
private bool CheckForCircularReference(object value, ReferenceLoopHandling? referenceLoopHandling, JsonContract contract)
private bool CheckForCircularReference(object value, JsonProperty property, JsonContract contract, JsonContainerContract collectionContract)
{
if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
return true;
ReferenceLoopHandling? referenceLoopHandling = null;
if (property != null)
referenceLoopHandling = property.ReferenceLoopHandling;
if (referenceLoopHandling == null && collectionContract != null)
referenceLoopHandling = collectionContract.ItemReferenceLoopHandling;
if (_serializeStack.IndexOf(value) != -1)
{
switch (referenceLoopHandling.GetValueOrDefault(Serializer.ReferenceLoopHandling))
@@ -299,13 +317,13 @@ namespace Newtonsoft.Json.Serialization
contract.InvokeOnSerialized(value, Serializer.Context);
}
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContract collectionValueContract)
private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
contract.InvokeOnSerializing(value, Serializer.Context);
_serializeStack.Add(value);
WriteObjectStart(writer, value, contract, member, collectionValueContract);
WriteObjectStart(writer, value, contract, member, collectionContract, collectionValueContract);
int initialDepth = writer.Top;
@@ -323,7 +341,7 @@ namespace Newtonsoft.Json.Serialization
if (ShouldWriteProperty(memberValue, property))
{
WriteMemberInfoProperty(writer, memberValue, property, memberContract);
WriteMemberInfoProperty(writer, memberValue, property, memberContract, contract);
}
}
}
@@ -343,17 +361,17 @@ namespace Newtonsoft.Json.Serialization
contract.InvokeOnSerialized(value, Serializer.Context);
}
private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContract collectionValueContract)
private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
writer.WriteStartObject();
bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
bool isReference = ResolveIsReference(contract, member, collectionContract) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
if (isReference)
{
writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value));
}
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, collectionValueContract))
{
WriteTypeProperty(writer, contract.UnderlyingType);
}
@@ -380,15 +398,15 @@ namespace Newtonsoft.Json.Serialization
return ((value & flag) == flag);
}
private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract)
private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
if (ShouldWriteReference(value, null, contract))
if (ShouldWriteReference(value, null, contract, collectionContract))
{
WriteReference(writer, value);
}
else
{
if (!CheckForCircularReference(value, null, contract))
if (!CheckForCircularReference(value, null, contract, collectionContract))
return;
_serializeStack.Add(value);
@@ -399,13 +417,13 @@ namespace Newtonsoft.Json.Serialization
}
}
private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContract collectionValueContract)
private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
contract.InvokeOnSerializing(values.UnderlyingCollection, Serializer.Context);
_serializeStack.Add(values.UnderlyingCollection);
bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionValueContract);
bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, collectionValueContract);
writer.WriteStartArray();
@@ -421,15 +439,15 @@ namespace Newtonsoft.Json.Serialization
{
JsonContract valueContract = collectionItemValueContract ?? GetContractSafe(value);
if (ShouldWriteReference(value, null, valueContract))
if (ShouldWriteReference(value, null, valueContract, contract))
{
WriteReference(writer, value);
}
else
{
if (CheckForCircularReference(value, null, contract))
if (CheckForCircularReference(value, null, valueContract, contract))
{
SerializeValue(writer, value, valueContract, null, contract.CollectionItemContract);
SerializeValue(writer, value, valueContract, null, contract, contract.CollectionItemContract);
}
}
}
@@ -456,10 +474,10 @@ namespace Newtonsoft.Json.Serialization
contract.InvokeOnSerialized(values.UnderlyingCollection, Serializer.Context);
}
private bool WriteStartArray(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContract collectionValueContract)
private bool WriteStartArray(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionValueContract);
bool isReference = ResolveIsReference(contract, member, collectionContract) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionContract, collectionValueContract);
bool writeMetadataObject = isReference || includeTypeDetails;
if (writeMetadataObject)
@@ -489,7 +507,7 @@ namespace Newtonsoft.Json.Serialization
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Security.SecuritySafeCriticalAttribute")]
[SecuritySafeCritical]
#endif
private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContract collectionValueContract)
private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
if (!JsonTypeReflector.FullyTrusted)
{
@@ -500,7 +518,7 @@ To fix this error either change the environment to be fully trusted, change the
contract.InvokeOnSerializing(value, Serializer.Context);
_serializeStack.Add(value);
WriteObjectStart(writer, value, contract, member, collectionValueContract);
WriteObjectStart(writer, value, contract, member, collectionContract, collectionValueContract);
SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter());
value.GetObjectData(serializationInfo, Serializer.Context);
@@ -508,7 +526,7 @@ To fix this error either change the environment to be fully trusted, change the
foreach (SerializationEntry serializationEntry in serializationInfo)
{
writer.WritePropertyName(serializationEntry.Name);
SerializeValue(writer, serializationEntry.Value, GetContractSafe(serializationEntry.Value), null, null);
SerializeValue(writer, serializationEntry.Value, GetContractSafe(serializationEntry.Value), null, null, null);
}
writer.WriteEndObject();
@@ -519,12 +537,12 @@ To fix this error either change the environment to be fully trusted, change the
#endif
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContract collectionValueContract)
private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
contract.InvokeOnSerializing(value, Serializer.Context);
_serializeStack.Add(value);
WriteObjectStart(writer, value, contract, member, collectionValueContract);
WriteObjectStart(writer, value, contract, member, collectionContract, collectionValueContract);
foreach (string memberName in value.GetDynamicMemberNames())
{
@@ -536,7 +554,7 @@ To fix this error either change the environment to be fully trusted, change the
: memberName;
writer.WritePropertyName(resolvedPropertyName);
SerializeValue(writer, memberValue, GetContractSafe(memberValue), null, null);
SerializeValue(writer, memberValue, GetContractSafe(memberValue), null, null, null);
}
}
@@ -547,9 +565,13 @@ To fix this error either change the environment to be fully trusted, change the
}
#endif
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContract collectionValueContract)
private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeNameHandlingFlag))
TypeNameHandling resolvedTypeNameHandling = ((member != null) ? member.TypeNameHandling : null)
?? ((collectionContract != null) ? collectionContract.ItemTypeNameHandling : null)
?? Serializer.TypeNameHandling;
if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag))
return true;
if (member != null)
@@ -573,13 +595,13 @@ To fix this error either change the environment to be fully trusted, change the
return false;
}
private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContract collectionValueContract)
private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonContract collectionValueContract)
{
contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context);
_serializeStack.Add(values.UnderlyingDictionary);
WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionValueContract);
WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionContract, collectionValueContract);
if (contract.DictionaryValueContract == null)
contract.DictionaryValueContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
@@ -604,19 +626,19 @@ To fix this error either change the environment to be fully trusted, change the
object value = entry.Value;
JsonContract valueContract = dictionaryValueContract ?? GetContractSafe(value);
if (ShouldWriteReference(value, null, valueContract))
if (ShouldWriteReference(value, null, valueContract, contract))
{
writer.WritePropertyName(propertyName);
WriteReference(writer, value);
}
else
{
if (!CheckForCircularReference(value, null, contract))
if (!CheckForCircularReference(value, null, valueContract, contract))
continue;
writer.WritePropertyName(propertyName);
SerializeValue(writer, value, valueContract, null, contract.DictionaryValueContract);
SerializeValue(writer, value, valueContract, null, contract, dictionaryValueContract);
}
}
catch (Exception ex)
@@ -102,6 +102,11 @@ namespace Newtonsoft.Json.Serialization
return GetJsonContainerAttribute(type) as JsonArrayAttribute;
}
public static JsonDictionaryAttribute GetJsonDictionaryAttribute(Type type)
{
return GetJsonContainerAttribute(type) as JsonDictionaryAttribute;
}
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
public static SerializableAttribute GetSerializableAttribute(Type type)
{
@@ -212,9 +217,6 @@ namespace Newtonsoft.Json.Serialization
{
JsonConverter memberConverter = JsonConverterAttribute.CreateJsonConverterInstance(converterType);
if (!memberConverter.CanConvert(targetConvertedType))
throw new JsonSerializationException("JsonConverter {0} on {1} is not compatible with member type {2}.".FormatWith(CultureInfo.InvariantCulture, memberConverter.GetType().Name, provider, targetConvertedType.Name));
return memberConverter;
}