diff --git a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs index 6f7fc6b5..1af0ea62 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs @@ -114,6 +114,35 @@ namespace Newtonsoft.Json.Tests.Converters return node; } +#if !NET20 + [Test] + public void SerializeEmptyDocument() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + + string json = JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true); + Assert.AreEqual("null", json); + + doc = new XmlDocument(); + doc.LoadXml(""); + + json = JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true); + Assert.AreEqual("null", json); + + + XDocument doc1 = XDocument.Parse(""); + + json = JsonConvert.SerializeXNode(doc1, Formatting.Indented, true); + Assert.AreEqual("null", json); + + doc1 = XDocument.Parse(""); + + json = JsonConvert.SerializeXNode(doc1, Formatting.Indented, true); + Assert.AreEqual("null", json); + } +#endif + [Test] public void DocumentSerializeIndented() { diff --git a/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs b/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs index 55c962f7..7b970330 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/DynamicTests.cs @@ -712,27 +712,27 @@ namespace Newtonsoft.Json.Tests.Linq ""StockValue"": 22050.0 }", json); } + } - public class DynamicDictionary : DynamicObject + public class DynamicDictionary : DynamicObject + { + private readonly IDictionary _values = new Dictionary(); + + public override IEnumerable GetDynamicMemberNames() { - private readonly IDictionary _values = new Dictionary(); + return _values.Keys; + } - public override IEnumerable GetDynamicMemberNames() - { - return _values.Keys; - } + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + result = _values[binder.Name]; + return true; + } - public override bool TryGetMember(GetMemberBinder binder, out object result) - { - result = _values[binder.Name]; - return true; - } - - public override bool TrySetMember(SetMemberBinder binder, object value) - { - _values[binder.Name] = value; - return true; - } + public override bool TrySetMember(SetMemberBinder binder, object value) + { + _values[binder.Name] = value; + return true; } } } diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index e9fa4ea3..d086ee81 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.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.4.14902")] +[assembly: AssemblyFileVersion("4.5.4.14905")] #endif diff --git a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs index 2a5ee264..88cd8a0d 100644 --- a/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs +++ b/Src/Newtonsoft.Json.Tests/Schema/JsonSchemaGeneratorTests.cs @@ -751,6 +751,33 @@ namespace Newtonsoft.Json.Tests.Schema } }", json); } + + [Test] + public void GenerateForNullableInt32() + { + JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(); + + JsonSchema jsonSchema = jsonSchemaGenerator.Generate(typeof(NullableInt32TestClass)); + string json = jsonSchema.ToString(); + + Assert.AreEqual(@"{ + ""type"": ""object"", + ""properties"": { + ""Value"": { + ""required"": true, + ""type"": [ + ""integer"", + ""null"" + ] + } + } +}", json); + } + } + + public class NullableInt32TestClass + { + public int? Value { get; set; } } public class DMDSLBase diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 78e2d458..39eade3b 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -93,7 +93,7 @@ namespace Newtonsoft.Json.Tests.Serialization string jsonText = JsonConvert.SerializeObject(store); - Store deserializedStore = (Store) JsonConvert.DeserializeObject(jsonText, typeof (Store)); + Store deserializedStore = (Store)JsonConvert.DeserializeObject(jsonText, typeof(Store)); Assert.AreEqual(store.Establised, deserializedStore.Establised); Assert.AreEqual(store.product.Count, deserializedStore.product.Count); @@ -109,7 +109,7 @@ namespace Newtonsoft.Json.Tests.Serialization product.Name = "Apple"; product.ExpiryDate = new DateTime(2008, 12, 28); product.Price = 3.99M; - product.Sizes = new string[] {"Small", "Medium", "Large"}; + product.Sizes = new string[] { "Small", "Medium", "Large" }; string output = JsonConvert.SerializeObject(product); //{ @@ -123,7 +123,7 @@ namespace Newtonsoft.Json.Tests.Serialization // ] //} - Product deserializedProduct = (Product) JsonConvert.DeserializeObject(output, typeof (Product)); + Product deserializedProduct = (Product)JsonConvert.DeserializeObject(output, typeof(Product)); Assert.AreEqual("Apple", deserializedProduct.Name); Assert.AreEqual(new DateTime(2008, 12, 28), deserializedProduct.ExpiryDate); @@ -156,7 +156,7 @@ namespace Newtonsoft.Json.Tests.Serialization { string value = @"{""Name"":""Orange"", ""Price"":3.99, ""ExpiryDate"":""01/24/2010 12:00:00""}"; - Product p = JsonConvert.DeserializeObject(value, typeof (Product)) as Product; + Product p = JsonConvert.DeserializeObject(value, typeof(Product)) as Product; Assert.AreEqual("Orange", p.Name); Assert.AreEqual(new DateTime(2010, 1, 24, 12, 0, 0), p.ExpiryDate); @@ -174,15 +174,15 @@ namespace Newtonsoft.Json.Tests.Serialization #if !PocketPC && !NET20 && !WINDOWS_PHONE MemoryStream ms = new MemoryStream(); - DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof (Dictionary)); + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary)); serializer.WriteObject(ms, testDictionary); byte[] data = ms.ToArray(); string output = Encoding.UTF8.GetString(data, 0, data.Length); #endif - Dictionary deserializedDictionary = (Dictionary) JsonConvert.DeserializeObject(jsonText, typeof (Dictionary)); - DateTime deserializedDate = (DateTime) deserializedDictionary["date"]; + Dictionary deserializedDictionary = (Dictionary)JsonConvert.DeserializeObject(jsonText, typeof(Dictionary)); + DateTime deserializedDate = (DateTime)deserializedDictionary["date"]; Assert.AreEqual(dateValue, deserializedDate); } @@ -192,12 +192,12 @@ namespace Newtonsoft.Json.Tests.Serialization { MethodExecutorObject executorObject = new MethodExecutorObject(); executorObject.serverClassName = "BanSubs"; - executorObject.serverMethodParams = new object[] {"21321546", "101", "1236", "D:\\1.txt"}; + executorObject.serverMethodParams = new object[] { "21321546", "101", "1236", "D:\\1.txt" }; executorObject.clientGetResultFunction = "ClientBanSubsCB"; string output = JsonConvert.SerializeObject(executorObject); - MethodExecutorObject executorObject2 = JsonConvert.DeserializeObject(output, typeof (MethodExecutorObject)) as MethodExecutorObject; + MethodExecutorObject executorObject2 = JsonConvert.DeserializeObject(output, typeof(MethodExecutorObject)) as MethodExecutorObject; Assert.AreNotSame(executorObject, executorObject2); Assert.AreEqual(executorObject2.serverClassName, "BanSubs"); @@ -212,7 +212,7 @@ namespace Newtonsoft.Json.Tests.Serialization { string value = @"{""Name"":""Orange"", ""Price"":3.99, ""ExpiryDate"":""01/24/2010 12:00:00""}"; - Hashtable p = JsonConvert.DeserializeObject(value, typeof (Hashtable)) as Hashtable; + Hashtable p = JsonConvert.DeserializeObject(value, typeof(Hashtable)) as Hashtable; Assert.AreEqual("Orange", p["Name"].ToString()); } @@ -222,7 +222,7 @@ namespace Newtonsoft.Json.Tests.Serialization { string value = @"{""Name"":""Orange"", ""Hash"":{""ExpiryDate"":""01/24/2010 12:00:00"",""UntypedArray"":[""01/24/2010 12:00:00""]}}"; - TypedSubHashtable p = JsonConvert.DeserializeObject(value, typeof (TypedSubHashtable)) as TypedSubHashtable; + TypedSubHashtable p = JsonConvert.DeserializeObject(value, typeof(TypedSubHashtable)) as TypedSubHashtable; Assert.AreEqual("01/24/2010 12:00:00", p.Hash["ExpiryDate"].ToString()); Assert.AreEqual(@"[ @@ -365,11 +365,11 @@ keyword such as type of business."" ""torrentc"": ""1816000723"" }"; - JObject o = (JObject) JsonConvert.DeserializeObject(jsonText); + JObject o = (JObject)JsonConvert.DeserializeObject(jsonText); Assert.AreEqual(4, o.Children().Count()); - JToken torrentsArray = (JToken) o["torrents"]; - JToken nestedTorrentsArray = (JToken) torrentsArray[0]; + JToken torrentsArray = (JToken)o["torrents"]; + JToken nestedTorrentsArray = (JToken)torrentsArray[0]; Assert.AreEqual(nestedTorrentsArray.Children().Count(), 19); } @@ -422,7 +422,7 @@ keyword such as type of business."" [Test] public void ReadOnlyCollectionSerialize() { - ReadOnlyCollection r1 = new ReadOnlyCollection(new int[] {0, 1, 2, 3, 4}); + ReadOnlyCollection r1 = new ReadOnlyCollection(new int[] { 0, 1, 2, 3, 4 }); string jsonText = JsonConvert.SerializeObject(r1); @@ -437,8 +437,8 @@ keyword such as type of business."" { string json = @"[""PRE\u003cPOST""]"; - DataContractJsonSerializer s = new DataContractJsonSerializer(typeof (List)); - List dataContractResult = (List) s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json))); + DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List)); + List dataContractResult = (List)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json))); List jsonNetResult = JsonConvert.DeserializeObject>(json); @@ -456,8 +456,8 @@ keyword such as type of business."" List javaScriptSerializerResult = javaScriptSerializer.Deserialize>(json); #endif - DataContractJsonSerializer s = new DataContractJsonSerializer(typeof (List)); - List dataContractResult = (List) s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json))); + DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List)); + List dataContractResult = (List)s.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json))); List jsonNetResult = JsonConvert.DeserializeObject>(json); @@ -476,9 +476,9 @@ keyword such as type of business."" ExceptionAssert.Throws( @"Bad JSON escape sequence: \j. Path '', line 1, position 7.", () => - { - JsonConvert.DeserializeObject>(json); - }); + { + JsonConvert.DeserializeObject>(json); + }); } [Test] @@ -495,7 +495,7 @@ keyword such as type of business."" }; MemoryStream ms = new MemoryStream(); - DataContractJsonSerializer s = new DataContractJsonSerializer(typeof (List)); + DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(List)); s.WriteObject(ms, testDates); ms.Seek(0, SeekOrigin.Begin); StreamReader sr = new StreamReader(ms); @@ -561,9 +561,9 @@ keyword such as type of business."" { StringValue = "I am a string", IntValue = int.MaxValue, - NestedAnonymous = new {NestedValue = byte.MaxValue}, - NestedArray = new[] {1, 2}, - Product = new Product() {Name = "TestProduct"} + NestedAnonymous = new { NestedValue = byte.MaxValue }, + NestedArray = new[] { 1, 2 }, + Product = new Product() { Name = "TestProduct" } }; string json = JsonConvert.SerializeObject(anonymous); @@ -599,7 +599,7 @@ keyword such as type of business."" Assert.AreEqual(@"[{""Name"":""Test1"",""ExpiryDate"":""2000-01-01T00:00:00Z"",""Price"":0.0,""Sizes"":null},{""Name"":""Test2"",""ExpiryDate"":""2000-01-01T00:00:00Z"",""Price"":0.0,""Sizes"":null},{""Name"":""Test3"",""ExpiryDate"":""2000-01-01T00:00:00Z"",""Price"":0.0,""Sizes"":null}]", sw.GetStringBuilder().ToString()); - ProductCollection collectionNew = (ProductCollection) jsonSerializer.Deserialize(new JsonTextReader(new StringReader(sw.GetStringBuilder().ToString())), typeof (ProductCollection)); + ProductCollection collectionNew = (ProductCollection)jsonSerializer.Deserialize(new JsonTextReader(new StringReader(sw.GetStringBuilder().ToString())), typeof(ProductCollection)); CollectionAssert.AreEqual(collection, collectionNew); } @@ -654,7 +654,7 @@ keyword such as type of business."" JsonSerializer s = new JsonSerializer(); s.ObjectCreationHandling = ObjectCreationHandling.Replace; - ClassWithArray wibble = (ClassWithArray) s.Deserialize(new StringReader(json), typeof (ClassWithArray)); + ClassWithArray wibble = (ClassWithArray)s.Deserialize(new StringReader(json), typeof(ClassWithArray)); Assert.AreEqual("hello", wibble.Foo); @@ -750,7 +750,7 @@ keyword such as type of business."" { Guid guid = new Guid("BED7F4EA-1A96-11d2-8F08-00A0C9A6186D"); - string json = JsonConvert.SerializeObject(new ClassWithGuid {GuidField = guid}); + string json = JsonConvert.SerializeObject(new ClassWithGuid { GuidField = guid }); Assert.AreEqual(@"{""GuidField"":""bed7f4ea-1a96-11d2-8f08-00a0c9a6186d""}", json); ClassWithGuid c = JsonConvert.DeserializeObject(json); @@ -777,7 +777,7 @@ keyword such as type of business."" { TimeSpan ts = new TimeSpan(00, 23, 59, 1); - string json = JsonConvert.SerializeObject(new ClassWithTimeSpan {TimeSpanField = ts}, Formatting.Indented); + string json = JsonConvert.SerializeObject(new ClassWithTimeSpan { TimeSpanField = ts }, Formatting.Indented); Assert.AreEqual(@"{ ""TimeSpanField"": ""23:59:01"" }", json); @@ -807,8 +807,8 @@ keyword such as type of business."" ArrayList o = JsonConvert.DeserializeObject(jsonText); Assert.AreEqual(4, o.Count); - Assert.AreEqual(3, ((JArray) o[2]).Count); - Assert.AreEqual(0, ((JObject) o[3]).Count); + Assert.AreEqual(3, ((JArray)o[2]).Count); + Assert.AreEqual(0, ((JObject)o[3]).Count); } #endif @@ -891,7 +891,7 @@ keyword such as type of business."" public void SerializerShouldUseMemberConverter_IsoDate() { DateTime testDate = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); - MemberConverterClass m1 = new MemberConverterClass {DefaultConverter = testDate, MemberConverter = testDate}; + MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate }; string json = JsonConvert.SerializeObject(m1); Assert.AreEqual(@"{""DefaultConverter"":""1970-01-01T00:00:00Z"",""MemberConverter"":""1970-01-01T00:00:00Z""}", json); @@ -965,7 +965,7 @@ keyword such as type of business."" public void SerializerShouldUseMemberConverterOverArgumentConverter() { DateTime testDate = new DateTime(JsonConvert.InitialJavaScriptDateTicks, DateTimeKind.Utc); - MemberConverterClass m1 = new MemberConverterClass {DefaultConverter = testDate, MemberConverter = testDate}; + MemberConverterClass m1 = new MemberConverterClass { DefaultConverter = testDate, MemberConverter = testDate }; string json = JsonConvert.SerializeObject(m1, new JavaScriptDateTimeConverter()); Assert.AreEqual(@"{""DefaultConverter"":new Date(0),""MemberConverter"":""1970-01-01T00:00:00Z""}", json); @@ -1036,10 +1036,10 @@ keyword such as type of business."" { string json; - json = JsonConvert.SerializeObject((int?) null); + json = JsonConvert.SerializeObject((int?)null); Assert.AreEqual("null", json); - json = JsonConvert.SerializeObject((int?) 1); + json = JsonConvert.SerializeObject((int?)1); Assert.AreEqual("1", json); } @@ -1113,23 +1113,23 @@ keyword such as type of business."" [Test] public void SerializeTypeProperty() { - string boolRef = typeof (bool).AssemblyQualifiedName; - TypeClass typeClass = new TypeClass {TypeProperty = typeof (bool)}; + string boolRef = typeof(bool).AssemblyQualifiedName; + TypeClass typeClass = new TypeClass { TypeProperty = typeof(bool) }; string json = JsonConvert.SerializeObject(typeClass); Assert.AreEqual(@"{""TypeProperty"":""" + boolRef + @"""}", json); TypeClass typeClass2 = JsonConvert.DeserializeObject(json); - Assert.AreEqual(typeof (bool), typeClass2.TypeProperty); + Assert.AreEqual(typeof(bool), typeClass2.TypeProperty); - string jsonSerializerTestRef = typeof (JsonSerializerTest).AssemblyQualifiedName; - typeClass = new TypeClass {TypeProperty = typeof (JsonSerializerTest)}; + string jsonSerializerTestRef = typeof(JsonSerializerTest).AssemblyQualifiedName; + typeClass = new TypeClass { TypeProperty = typeof(JsonSerializerTest) }; json = JsonConvert.SerializeObject(typeClass); Assert.AreEqual(@"{""TypeProperty"":""" + jsonSerializerTestRef + @"""}", json); typeClass2 = JsonConvert.DeserializeObject(json); - Assert.AreEqual(typeof (JsonSerializerTest), typeClass2.TypeProperty); + Assert.AreEqual(typeof(JsonSerializerTest), typeClass2.TypeProperty); } [Test] @@ -1181,16 +1181,16 @@ keyword such as type of business."" ExceptionAssert.Throws( "Required property 'FirstName' expects a value but got null. Path '', line 6, position 2.", () => - { - string json = @"{ + { + string json = @"{ ""FirstName"": null, ""MiddleName"": null, ""LastName"": null, ""BirthDate"": ""\/Date(977309755000)\/"" }"; - JsonConvert.DeserializeObject(json); - }); + JsonConvert.DeserializeObject(json); + }); } [Test] @@ -1199,18 +1199,18 @@ keyword such as type of business."" ExceptionAssert.Throws( "Cannot write a null value for property 'FirstName'. Property requires a value.", () => - { - RequiredMembersClass requiredMembersClass = new RequiredMembersClass - { - FirstName = null, - BirthDate = new DateTime(2000, 10, 10, 10, 10, 10, DateTimeKind.Utc), - LastName = null, - MiddleName = null - }; + { + RequiredMembersClass requiredMembersClass = new RequiredMembersClass + { + FirstName = null, + BirthDate = new DateTime(2000, 10, 10, 10, 10, 10, DateTimeKind.Utc), + LastName = null, + MiddleName = null + }; - string json = JsonConvert.SerializeObject(requiredMembersClass); - Console.WriteLine(json); - }); + string json = JsonConvert.SerializeObject(requiredMembersClass); + Console.WriteLine(json); + }); } [Test] @@ -1219,13 +1219,13 @@ keyword such as type of business."" ExceptionAssert.Throws( "Required property 'LastName' not found in JSON. Path '', line 3, position 2.", () => - { - string json = @"{ + { + string json = @"{ ""FirstName"": ""Bob"" }"; - JsonConvert.DeserializeObject(json); - }); + JsonConvert.DeserializeObject(json); + }); } [Test] @@ -1234,7 +1234,7 @@ keyword such as type of business."" JaggedArray aa = new JaggedArray(); aa.Before = "Before!"; aa.After = "After!"; - aa.Coordinates = new[] {new[] {1, 1}, new[] {1, 2}, new[] {2, 1}, new[] {2, 2}}; + aa.Coordinates = new[] { new[] { 1, 1 }, new[] { 1, 2 }, new[] { 2, 1 }, new[] { 2, 2 } }; string json = JsonConvert.SerializeObject(aa); @@ -1313,9 +1313,9 @@ keyword such as type of business."" ExceptionAssert.Throws( @"Could not create an instance of type Newtonsoft.Json.Tests.TestObjects.ICo. Type is an interface or abstract class and cannot be instantated. Path 'co.Name', line 1, position 14.", () => - { - InterfacePropertyTestClass testFromDe = (InterfacePropertyTestClass) JsonConvert.DeserializeObject(strFromTest, typeof (InterfacePropertyTestClass)); - }); + { + InterfacePropertyTestClass testFromDe = (InterfacePropertyTestClass)JsonConvert.DeserializeObject(strFromTest, typeof(InterfacePropertyTestClass)); + }); } private Person GetPerson() @@ -1453,7 +1453,7 @@ keyword such as type of business."" ""ReferenceLoopHandlingSerializeProperty"": null }", json); - json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}); + json = JsonConvert.SerializeObject(o, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); Assert.AreEqual(@"{ ""DefaultValueHandlingIncludeProperty"": ""Default!"", @@ -1523,7 +1523,7 @@ keyword such as type of business."" } #if !(SILVERLIGHT || NET20 || NETFX_CORE || PORTABLE) - [MetadataType(typeof (OptInClassMetadata))] + [MetadataType(typeof(OptInClassMetadata))] public class OptInClass { [DataContract] @@ -1585,7 +1585,8 @@ keyword such as type of business."" Title = title; } - [DataMember] private string _name; + [DataMember] + private string _name; [DataMember(Name = "_age")] private int Age { get; set; } @@ -1636,7 +1637,7 @@ keyword such as type of business."" DictionaryInterfaceClass c = JsonConvert.DeserializeObject( json, - new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace}); + new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }); Assert.AreEqual("Name!", c.Name); Assert.AreEqual(1, c.Dictionary.Count); @@ -1666,7 +1667,7 @@ keyword such as type of business."" }"; DictionaryInterfaceClass c = JsonConvert.DeserializeObject(json, - new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Reuse}); + new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Reuse }); Assert.AreEqual("Name!", c.Name); Assert.AreEqual(3, c.Dictionary.Count); @@ -1694,7 +1695,7 @@ keyword such as type of business."" /*comment*/ ] /*comment*/ } /*comment*/"; - Product deserializedProduct = (Product) JsonConvert.DeserializeObject(json, typeof (Product)); + Product deserializedProduct = (Product)JsonConvert.DeserializeObject(json, typeof(Product)); Assert.AreEqual("Apple", deserializedProduct.Name); Assert.AreEqual(new DateTime(2008, 12, 28, 0, 0, 0, DateTimeKind.Utc), deserializedProduct.ExpiryDate); @@ -1846,11 +1847,11 @@ keyword such as type of business."" Assert.AreEqual("Navigate", o.Method); Assert.AreEqual(3, o.Data.Length); Assert.AreEqual("dashboard", o.Data[0]); - CustomAssert.IsInstanceOfType(typeof (JArray), o.Data[1]); - Assert.AreEqual(4, ((JArray) o.Data[1]).Count); - CustomAssert.IsInstanceOfType(typeof (JObject), o.Data[2]); - Assert.AreEqual(1, ((JObject) o.Data[2]).Count); - Assert.AreEqual(1, (int) ((JObject) o.Data[2])["one"]); + CustomAssert.IsInstanceOfType(typeof(JArray), o.Data[1]); + Assert.AreEqual(4, ((JArray)o.Data[1]).Count); + CustomAssert.IsInstanceOfType(typeof(JObject), o.Data[2]); + Assert.AreEqual(1, ((JObject)o.Data[2]).Count); + Assert.AreEqual(1, (int)((JObject)o.Data[2])["one"]); } [Test] @@ -1974,9 +1975,9 @@ keyword such as type of business."" ExceptionAssert.Throws( @"Unable to find a constructor to use for type Newtonsoft.Json.Tests.TestObjects.Event. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'sublocation', line 1, position 15.", () => - { - Event e = JsonConvert.DeserializeObject(json); - }); + { + Event e = JsonConvert.DeserializeObject(json); + }); } [Test] @@ -1985,10 +1986,10 @@ keyword such as type of business."" string json = @"{'SetOnlyProperty':[1,2,3,4,5]}"; SetOnlyPropertyClass2 setOnly = JsonConvert.DeserializeObject(json); - JArray a = (JArray) setOnly.GetValue(); + JArray a = (JArray)setOnly.GetValue(); Assert.AreEqual(5, a.Count); - Assert.AreEqual(1, (int) a[0]); - Assert.AreEqual(5, (int) a[a.Count - 1]); + Assert.AreEqual(1, (int)a[0]); + Assert.AreEqual(5, (int)a[a.Count - 1]); } [Test] @@ -2061,9 +2062,9 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa ExceptionAssert.Throws( @"Cannot populate JSON object onto type 'System.Collections.Generic.List`1[Newtonsoft.Json.Tests.TestObjects.Person]'. Path '', line 1, position 2.", () => - { - JsonConvert.PopulateObject(json, new List()); - }); + { + JsonConvert.PopulateObject(json, new List()); + }); } [Test] @@ -2119,17 +2120,17 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa ExceptionAssert.Throws( @"Could not convert string to integer: . Path 'ReadTimeout', line 1, position 15.", () => - { - JsonConvert.DeserializeObject("{ReadTimeout:''}", new JsonSerializerSettings - { - ContractResolver = new DefaultContractResolver - { + { + JsonConvert.DeserializeObject("{ReadTimeout:''}", new JsonSerializerSettings + { + ContractResolver = new DefaultContractResolver + { #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - IgnoreSerializableAttribute = true + IgnoreSerializableAttribute = true #endif - } - }); - }); + } + }); + }); } [Test] @@ -2138,17 +2139,17 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa ExceptionAssert.Throws( @"Error converting value {null} to type 'System.Int32'. Path 'ReadTimeout', line 1, position 17.", () => + { + JsonConvert.DeserializeObject("{ReadTimeout:null}", new JsonSerializerSettings { - JsonConvert.DeserializeObject("{ReadTimeout:null}", new JsonSerializerSettings + ContractResolver = new DefaultContractResolver { - ContractResolver = new DefaultContractResolver - { #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - IgnoreSerializableAttribute = true + IgnoreSerializableAttribute = true #endif - } - }); + } }); + }); } [Test] @@ -2210,9 +2211,9 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public void SerializeListWithJsonConverter() { Foo f = new Foo(); - f.Bars.Add(new Bar {Id = 0}); - f.Bars.Add(new Bar {Id = 1}); - f.Bars.Add(new Bar {Id = 2}); + f.Bars.Add(new Bar { Id = 0 }); + f.Bars.Add(new Bar { Id = 1 }); + f.Bars.Add(new Bar { Id = 2 }); string json = JsonConvert.SerializeObject(f, Formatting.Indented); Assert.AreEqual(@"{ @@ -2248,8 +2249,8 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public void SerializePersonKeyedDictionary() { Dictionary dictionary = new Dictionary(); - dictionary.Add(new Person {Name = "p1"}, 1); - dictionary.Add(new Person {Name = "p2"}, 2); + dictionary.Add(new Person { Name = "p1" }, 1); + dictionary.Add(new Person { Name = "p2" }, 2); string json = JsonConvert.SerializeObject(dictionary, Formatting.Indented); @@ -2360,7 +2361,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public void DeserializeBaseReferenceWithDerivedValue() { PersonPropertyClass personPropertyClass = new PersonPropertyClass(); - WagePerson wagePerson = (WagePerson) personPropertyClass.Person; + WagePerson wagePerson = (WagePerson)personPropertyClass.Person; wagePerson.BirthDate = new DateTime(2000, 11, 29, 23, 59, 59, DateTimeKind.Utc); wagePerson.Department = "McDees"; @@ -2381,7 +2382,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa json); PersonPropertyClass newPersonPropertyClass = JsonConvert.DeserializeObject(json); - Assert.AreEqual(wagePerson.HourlyWage, ((WagePerson) newPersonPropertyClass.Person).HourlyWage); + Assert.AreEqual(wagePerson.HourlyWage, ((WagePerson)newPersonPropertyClass.Person).HourlyWage); } public class ExistingValueClass @@ -2409,8 +2410,8 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa Assert.IsNotNull(d); Assert.IsNotNull(d.Dictionary); - Assert.AreEqual(typeof (Dictionary), d.Dictionary.GetType()); - Assert.AreEqual(typeof (List), d.List.GetType()); + Assert.AreEqual(typeof(Dictionary), d.Dictionary.GetType()); + Assert.AreEqual(typeof(List), d.List.GetType()); Assert.AreEqual(2, d.Dictionary.Count); Assert.AreEqual("new", d.Dictionary["existing"]); Assert.AreEqual("appended", d.Dictionary["appended"]); @@ -2485,8 +2486,8 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa { ThisGenericTest g = new ThisGenericTest(); - g.Add(new KeyValueId {Id = 1, Key = "key1", Value = "value1"}); - g.Add(new KeyValueId {Id = 2, Key = "key2", Value = "value2"}); + g.Add(new KeyValueId { Id = 1, Key = "key1", Value = "value1" }); + g.Add(new KeyValueId { Id = 2, Key = "key2", Value = "value2" }); g.MyProperty = "some value"; @@ -2535,9 +2536,9 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa ExceptionAssert.Throws( "Unable to find a default constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+DictionaryWithNoDefaultConstructor. Path 'key1', line 1, position 6.", () => - { - JsonConvert.DeserializeObject(json); - }); + { + JsonConvert.DeserializeObject(json); + }); } public class DictionaryWithNoDefaultConstructor : Dictionary @@ -2554,7 +2555,8 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa [JsonObject(MemberSerialization.OptIn)] public class A { - [JsonProperty("A1")] private string _A1; + [JsonProperty("A1")] + private string _A1; public string A1 { @@ -2571,7 +2573,8 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa { public string B1 { get; set; } - [JsonProperty("B2")] private string _B2; + [JsonProperty("B2")] + private string _B2; public string B2 { @@ -2621,7 +2624,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa { public override string Name { - get { return typeof (Human).Name; } + get { return typeof(Human).Name; } } public string Ethnicity { get; set; } @@ -2644,13 +2647,13 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa DataContractJsonSerializerTestClass c = new DataContractJsonSerializerTestClass(); c.TimeSpanProperty = new TimeSpan(200, 20, 59, 30, 900); c.GuidProperty = new Guid("66143115-BE2A-4a59-AF0A-348E1EA15B1E"); - c.AnimalProperty = new Human() {Ethnicity = "European"}; + c.AnimalProperty = new Human() { Ethnicity = "European" }; c.ExceptionProperty = ex; MemoryStream ms = new MemoryStream(); DataContractJsonSerializer serializer = new DataContractJsonSerializer( - typeof (DataContractJsonSerializerTestClass), - new Type[] {typeof (Human)}); + typeof(DataContractJsonSerializerTestClass), + new Type[] { typeof(Human) }); serializer.WriteObject(ms, c); byte[] jsonBytes = ms.ToArray(); @@ -2695,7 +2698,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public bool IsReadOnly { - get { return ((IDictionary) _innerDictionary).IsReadOnly; } + get { return ((IDictionary)_innerDictionary).IsReadOnly; } } public ICollection Keys @@ -2721,7 +2724,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public void Add(KeyValuePair item) { - ((IDictionary) _innerDictionary).Add(item); + ((IDictionary)_innerDictionary).Add(item); } public void Add(string key, T value) @@ -2736,7 +2739,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public bool Contains(KeyValuePair item) { - return ((IDictionary) _innerDictionary).Contains(item); + return ((IDictionary)_innerDictionary).Contains(item); } public bool ContainsKey(string key) @@ -2746,7 +2749,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public void CopyTo(KeyValuePair[] array, int arrayIndex) { - ((IDictionary) _innerDictionary).CopyTo(array, arrayIndex); + ((IDictionary)_innerDictionary).CopyTo(array, arrayIndex); } public IEnumerator> GetEnumerator() @@ -2769,7 +2772,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa public bool Remove(KeyValuePair item) { - return ((IDictionary) _innerDictionary).Remove(item); + return ((IDictionary)_innerDictionary).Remove(item); } public bool Remove(string key) @@ -2784,7 +2787,7 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa IEnumerator IEnumerable.GetEnumerator() { - return ((IEnumerable) _innerDictionary).GetEnumerator(); + return ((IEnumerable)_innerDictionary).GetEnumerator(); } } @@ -2838,10 +2841,10 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa { _stringValue = info.GetString("stringValue"); _intValue = info.GetInt32("intValue"); - _dateTimeOffsetValue = (DateTimeOffset) info.GetValue("dateTimeOffsetValue", typeof (DateTimeOffset)); - _personValue = (Person) info.GetValue("personValue", typeof (Person)); - _nullPersonValue = (Person) info.GetValue("nullPersonValue", typeof (Person)); - _nullableInt = (int?) info.GetValue("nullableInt", typeof (int?)); + _dateTimeOffsetValue = (DateTimeOffset)info.GetValue("dateTimeOffsetValue", typeof(DateTimeOffset)); + _personValue = (Person)info.GetValue("personValue", typeof(Person)); + _nullPersonValue = (Person)info.GetValue("nullPersonValue", typeof(Person)); + _nullableInt = (int?)info.GetValue("nullableInt", typeof(int?)); _booleanValue = info.GetBoolean("booleanValue"); _byteValue = info.GetByte("byteValue"); @@ -2926,11 +2929,11 @@ To force JSON objects to deserialize add the JsonObjectAttribute to the type. Pa @"Type 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ISerializableTestObject' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data. To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add to JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true. Path 'booleanValue', line 1, position 14.", () => - { - JsonTypeReflector.SetFullyTrusted(false); + { + JsonTypeReflector.SetFullyTrusted(false); - JsonConvert.DeserializeObject("{booleanValue:true}"); - }); + JsonConvert.DeserializeObject("{booleanValue:true}"); + }); } finally { @@ -3146,14 +3149,14 @@ To fix this error either change the environment to be fully trusted, change the ""AA_property6"": 2 }"); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myA)); - Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof (AA).GetField("AA_field2", BindingFlags.Instance | BindingFlags.NonPublic), myA)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myA)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myA)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myA)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myA)); - Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myA)); - Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field2", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myA)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myA)); BB myB = JsonConvert.DeserializeObject( @"{ @@ -3177,30 +3180,31 @@ To fix this error either change the environment to be fully trusted, change the ""BB_property8"": 3 }"); - Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof (AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myB)); - Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof (AA).GetField("AA_field2", BindingFlags.Instance | BindingFlags.NonPublic), myB)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myB)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myB)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myB)); - Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB)); - Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myB)); - Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof (AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field1", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetField("AA_field2", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property1", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property2", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property3", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(2, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property5", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(0, ReflectionUtils.GetMemberValue(typeof(AA).GetProperty("AA_property6", BindingFlags.Instance | BindingFlags.NonPublic), myB)); Assert.AreEqual(4, myB.BB_field1); Assert.AreEqual(4, myB.BB_field2); Assert.AreEqual(3, myB.BB_property1); Assert.AreEqual(3, myB.BB_property2); - Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof (BB).GetProperty("BB_property3", BindingFlags.Instance | BindingFlags.Public), myB)); - Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof (BB).GetProperty("BB_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property3", BindingFlags.Instance | BindingFlags.Public), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property4", BindingFlags.Instance | BindingFlags.NonPublic), myB)); Assert.AreEqual(0, myB.BB_property5); - Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof (BB).GetProperty("BB_property6", BindingFlags.Instance | BindingFlags.Public), myB)); - Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof (BB).GetProperty("BB_property7", BindingFlags.Instance | BindingFlags.Public), myB)); - Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof (BB).GetProperty("BB_property8", BindingFlags.Instance | BindingFlags.Public), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property6", BindingFlags.Instance | BindingFlags.Public), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property7", BindingFlags.Instance | BindingFlags.Public), myB)); + Assert.AreEqual(3, ReflectionUtils.GetMemberValue(typeof(BB).GetProperty("BB_property8", BindingFlags.Instance | BindingFlags.Public), myB)); } public class AA { - [JsonProperty] protected int AA_field1; + [JsonProperty] + protected int AA_field1; protected int AA_field2; [JsonProperty] @@ -3237,7 +3241,8 @@ To fix this error either change the environment to be fully trusted, change the public class BB : AA { - [JsonProperty] public int BB_field1; + [JsonProperty] + public int BB_field1; public int BB_field2; [JsonProperty] @@ -3353,8 +3358,8 @@ To fix this error either change the environment to be fully trusted, change the { ClientMap source = new ClientMap() { - position = new Pos() {X = 100, Y = 200}, - center = new PosDouble() {X = 251.6, Y = 361.3} + position = new Pos() { X = 100, Y = 200 }, + center = new PosDouble() { X = 251.6, Y = 361.3 } }; string json = JsonConvert.SerializeObject(source, new PosConverter(), new PosDoubleConverter()); @@ -3383,7 +3388,7 @@ To fix this error either change the environment to be fully trusted, change the { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - Pos p = (Pos) value; + Pos p = (Pos)value; if (p != null) writer.WriteRawValue(String.Format("new Pos({0},{1})", p.X, p.Y)); @@ -3398,7 +3403,7 @@ To fix this error either change the environment to be fully trusted, change the public override bool CanConvert(Type objectType) { - return objectType.IsAssignableFrom(typeof (Pos)); + return objectType.IsAssignableFrom(typeof(Pos)); } } @@ -3406,7 +3411,7 @@ To fix this error either change the environment to be fully trusted, change the { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - PosDouble p = (PosDouble) value; + PosDouble p = (PosDouble)value; if (p != null) writer.WriteRawValue(String.Format(CultureInfo.InvariantCulture, "new PosD({0},{1})", p.X, p.Y)); @@ -3421,7 +3426,7 @@ To fix this error either change the environment to be fully trusted, change the public override bool CanConvert(Type objectType) { - return objectType.IsAssignableFrom(typeof (PosDouble)); + return objectType.IsAssignableFrom(typeof(PosDouble)); } } @@ -3462,7 +3467,7 @@ To fix this error either change the environment to be fully trusted, change the GenericListTestClass newValue = JsonConvert.DeserializeObject(json); Assert.AreEqual(2, newValue.GenericList.Count); - Assert.AreEqual(typeof (List), newValue.GenericList.GetType()); + Assert.AreEqual(typeof(List), newValue.GenericList.GetType()); } [Test] @@ -3545,14 +3550,14 @@ To fix this error either change the environment to be fully trusted, change the public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - List existingStrings = (List) existingValue; + List existingStrings = (List)existingValue; List newStrings = new List(existingStrings); reader.Read(); while (reader.TokenType != JsonToken.EndArray) { - string s = (string) reader.Value; + string s = (string)reader.Value; newStrings.Add(s); reader.Read(); @@ -3563,7 +3568,7 @@ To fix this error either change the environment to be fully trusted, change the public override bool CanConvert(Type objectType) { - return (objectType == typeof (List)); + return (objectType == typeof(List)); } } @@ -3571,11 +3576,11 @@ To fix this error either change the environment to be fully trusted, change the public void StringListAppenderConverterTest() { Movie p = new Movie(); - p.ReleaseCountries = new List {"Existing"}; + p.ReleaseCountries = new List { "Existing" }; JsonConvert.PopulateObject("{'ReleaseCountries':['Appended']}", p, new JsonSerializerSettings { - Converters = new List {new StringListAppenderConverter()} + Converters = new List { new StringListAppenderConverter() } }); Assert.AreEqual(2, p.ReleaseCountries.Count); @@ -3592,15 +3597,15 @@ To fix this error either change the environment to be fully trusted, change the public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - string existingString = (string) existingValue; - string newString = existingString + (string) reader.Value; + string existingString = (string)existingValue; + string newString = existingString + (string)reader.Value; return newString; } public override bool CanConvert(Type objectType) { - return (objectType == typeof (string)); + return (objectType == typeof(string)); } } @@ -3612,7 +3617,7 @@ To fix this error either change the environment to be fully trusted, change the JsonConvert.PopulateObject("{'Name':'Appended'}", p, new JsonSerializerSettings { - Converters = new List {new StringAppenderConverter()} + Converters = new List { new StringAppenderConverter() } }); Assert.AreEqual("Existing,Appended", p.Name); @@ -3637,9 +3642,9 @@ To fix this error either change the environment to be fully trusted, change the ExceptionAssert.Throws( "Additional content found in JSON reference object. A JSON reference object should only have a $ref property. Path 'Father.$id', line 6, position 11.", () => - { - JsonConvert.DeserializeObject>(json); - }); + { + JsonConvert.DeserializeObject>(json); + }); } [Test] @@ -3682,8 +3687,8 @@ To fix this error either change the environment to be fully trusted, change the Dictionary result = JsonConvert.DeserializeObject>(json); Assert.AreEqual(3, result.Count); - Assert.AreEqual(1, ((JObject) result["Father"]).Count); - Assert.AreEqual("blah!", (string) ((JObject) result["Father"])["blah"]); + Assert.AreEqual(1, ((JObject)result["Father"]).Count); + Assert.AreEqual("blah!", (string)((JObject)result["Father"])["blah"]); } public class ConstructorCompexIgnoredProperty @@ -3778,7 +3783,7 @@ To fix this error either change the environment to be fully trusted, change the joe.Manager = mike; mike.Manager = mike; - string json = JsonConvert.SerializeObject(new[] {joe, mike}, Formatting.Indented); + string json = JsonConvert.SerializeObject(new[] { joe, mike }, Formatting.Indented); // [ // { // "Name": "Joe Employee", @@ -3815,9 +3820,12 @@ To fix this error either change the environment to be fully trusted, change the set { _nameSpecified = value; } } - [JsonIgnore] public bool WeightSpecified; + [JsonIgnore] + public bool WeightSpecified; - [JsonIgnore] [System.Xml.Serialization.XmlIgnoreAttribute] public bool HeightSpecified; + [JsonIgnore] + [System.Xml.Serialization.XmlIgnoreAttribute] + public bool HeightSpecified; [JsonIgnore] @@ -3921,7 +3929,8 @@ To fix this error either change the environment to be fully trusted, change the public string FirstOrder; // Use the XmlIgnoreAttribute to ignore the // special field named "FirstOrderSpecified". - [System.Xml.Serialization.XmlIgnoreAttribute] public bool FirstOrderSpecified; + [System.Xml.Serialization.XmlIgnoreAttribute] + public bool FirstOrderSpecified; } public class FamilyDetails @@ -3946,7 +3955,7 @@ To fix this error either change the environment to be fully trusted, change the martha.NumberOfChildren = 3; martha.NumberOfChildrenSpecified = false; - string json = JsonConvert.SerializeObject(new[] {joe, martha}, Formatting.Indented); + string json = JsonConvert.SerializeObject(new[] { joe, martha }, Formatting.Indented); //[ // { // "Name": "Joe Family Details", @@ -3980,7 +3989,7 @@ To fix this error either change the environment to be fully trusted, change the public static implicit operator DictionaryKey(string value) { - return new DictionaryKey() {Value = value}; + return new DictionaryKey() { Value = value }; } } @@ -3989,8 +3998,8 @@ To fix this error either change the environment to be fully trusted, change the { Dictionary dictionary = new Dictionary(); - dictionary.Add(new DictionaryKey() {Value = "First!"}, "First"); - dictionary.Add(new DictionaryKey() {Value = "Second!"}, "Second"); + dictionary.Add(new DictionaryKey() { Value = "First!" }, "First"); + dictionary.Add(new DictionaryKey() { Value = "Second!" }, "Second"); string json = JsonConvert.SerializeObject(dictionary, Formatting.Indented); @@ -4008,7 +4017,7 @@ To fix this error either change the environment to be fully trusted, change the [Test] public void SerializeNullableArray() { - string jsonText = JsonConvert.SerializeObject(new double?[] {2.4, 4.3, null}, Formatting.Indented); + string jsonText = JsonConvert.SerializeObject(new double?[] { 2.4, 4.3, null }, Formatting.Indented); Assert.AreEqual(@"[ 2.4, @@ -4016,7 +4025,7 @@ To fix this error either change the environment to be fully trusted, change the null ]", jsonText); - double?[] d = (double?[]) JsonConvert.DeserializeObject(jsonText, typeof (double?[])); + double?[] d = (double?[])JsonConvert.DeserializeObject(jsonText, typeof(double?[])); Assert.AreEqual(3, d.Length); Assert.AreEqual(2.4, d[0]); @@ -4071,7 +4080,7 @@ To fix this error either change the environment to be fully trusted, change the JsonTextReader reader = new JsonTextReader(new StringReader(json)); - MyClass[] z = (MyClass[]) serializer1.Deserialize(reader, typeof (MyClass[])); + MyClass[] z = (MyClass[])serializer1.Deserialize(reader, typeof(MyClass[])); Assert.AreEqual(2, z.Length); Assert.AreEqual(0, z[0].Prop1.Length); Assert.AreEqual(0, z[1].Prop1.Length); @@ -4233,19 +4242,19 @@ To fix this error either change the environment to be fully trusted, change the IDictionary newExpando = JsonConvert.DeserializeObject(json); - CustomAssert.IsInstanceOfType(typeof (long), newExpando["Int"]); + CustomAssert.IsInstanceOfType(typeof(long), newExpando["Int"]); Assert.AreEqual((long)expando.Int, newExpando["Int"]); - CustomAssert.IsInstanceOfType(typeof (double), newExpando["Decimal"]); + CustomAssert.IsInstanceOfType(typeof(double), newExpando["Decimal"]); Assert.AreEqual(expando.Decimal, newExpando["Decimal"]); - CustomAssert.IsInstanceOfType(typeof (ExpandoObject), newExpando["Complex"]); - IDictionary o = (ExpandoObject) newExpando["Complex"]; + CustomAssert.IsInstanceOfType(typeof(ExpandoObject), newExpando["Complex"]); + IDictionary o = (ExpandoObject)newExpando["Complex"]; - CustomAssert.IsInstanceOfType(typeof (string), o["String"]); + CustomAssert.IsInstanceOfType(typeof(string), o["String"]); Assert.AreEqual(expando.Complex.String, o["String"]); - CustomAssert.IsInstanceOfType(typeof (DateTime), o["DateTime"]); + CustomAssert.IsInstanceOfType(typeof(DateTime), o["DateTime"]); Assert.AreEqual(expando.Complex.DateTime, o["DateTime"]); } #endif @@ -4309,7 +4318,7 @@ To fix this error either change the environment to be fully trusted, change the public void DeserializeStructProperty() { VectorParent obj = new VectorParent(); - obj.Position = new Vector {X = 1, Y = 2, Z = 3}; + obj.Position = new Vector { X = 1, Y = 2, Z = 3 }; string str = JsonConvert.SerializeObject(obj); @@ -4368,7 +4377,7 @@ To fix this error either change the environment to be fully trusted, change the var meh = JsonConvert.DeserializeObject(json, settings); - Assert.AreEqual(((Derived) meh).IDoWork, "woo"); + Assert.AreEqual(((Derived)meh).IDoWork, "woo"); Assert.AreEqual(meh.IDontWork, "meh"); } @@ -4421,11 +4430,11 @@ To fix this error either change the environment to be fully trusted, change the public void DeserializeNullableStruct() { NullableStructPropertyClass nullableStructPropertyClass = new NullableStructPropertyClass(); - nullableStructPropertyClass.Foo1 = new StructISerializable() {Name = "foo 1"}; - nullableStructPropertyClass.Foo2 = new StructISerializable() {Name = "foo 2"}; + nullableStructPropertyClass.Foo1 = new StructISerializable() { Name = "foo 1" }; + nullableStructPropertyClass.Foo2 = new StructISerializable() { Name = "foo 2" }; NullableStructPropertyClass barWithNull = new NullableStructPropertyClass(); - barWithNull.Foo1 = new StructISerializable() {Name = "foo 1"}; + barWithNull.Foo1 = new StructISerializable() { Name = "foo 1" }; barWithNull.Foo2 = null; //throws error on deserialization because bar1.Foo2 is of type Foo? @@ -4599,7 +4608,7 @@ To fix this error either change the environment to be fully trusted, change the { EnumerableClass c = new EnumerableClass { - Enumerable = new List {"One", "Two", "Three"} + Enumerable = new List { "One", "Two", "Three" } }; string json = JsonConvert.SerializeObject(c, Formatting.Indented); @@ -4673,15 +4682,15 @@ To fix this error either change the environment to be fully trusted, change the ExceptionAssert.Throws( "Error converting value {null} to type 'System.DateTime'. Path '', line 1, position 4.", () => - { - JsonConvert.DeserializeObject("null", typeof (DateTime)); - }); + { + JsonConvert.DeserializeObject("null", typeof(DateTime)); + }); } [Test] public void DeserializeNullNullableDateTimeValueTest() { - object dateTime = JsonConvert.DeserializeObject("null", typeof (DateTime?)); + object dateTime = JsonConvert.DeserializeObject("null", typeof(DateTime?)); Assert.IsNull(dateTime); } @@ -4783,7 +4792,7 @@ To fix this error either change the environment to be fully trusted, change the { get { - return new[] {1, 2, 3}; //fails + return new[] { 1, 2, 3 }; //fails //return new List(new[] { 1, 2, 3 }); //works } } @@ -4879,7 +4888,7 @@ To fix this error either change the environment to be fully trusted, change the public interface IInterfaceObject { [JsonProperty(PropertyName = "virtualMember")] - [JsonConverter(typeof (IsoDateTimeConverter))] + [JsonConverter(typeof(IsoDateTimeConverter))] DateTime InterfaceMember { get; set; } } @@ -5086,9 +5095,12 @@ To fix this error either change the environment to be fully trusted, change the _readonlyString = "default!"; } - [JsonProperty] private string _privateString; - [JsonProperty] private readonly string _readonlyString; - [JsonProperty] internal string _internalString; + [JsonProperty] + private string _privateString; + [JsonProperty] + private readonly string _readonlyString; + [JsonProperty] + internal string _internalString; public string UseValue() { @@ -5134,19 +5146,27 @@ To fix this error either change the environment to be fully trusted, change the public class BaseType { - [DataMember] public string zebra; + [DataMember] + public string zebra; } [DataContract] public class DerivedType : BaseType { - [DataMember(Order = 0)] public string bird; - [DataMember(Order = 1)] public string parrot; - [DataMember] public string dog; - [DataMember(Order = 3)] public string antelope; - [DataMember] public string cat; - [JsonProperty(Order = 1)] public string albatross; - [JsonProperty(Order = -2)] public string dinosaur; + [DataMember(Order = 0)] + public string bird; + [DataMember(Order = 1)] + public string parrot; + [DataMember] + public string dog; + [DataMember(Order = 3)] + public string antelope; + [DataMember] + public string cat; + [JsonProperty(Order = 1)] + public string albatross; + [JsonProperty(Order = -2)] + public string dinosaur; } [Test] @@ -5293,7 +5313,7 @@ To fix this error either change the environment to be fully trusted, change the public void UsingJsonTextWriter() { // The property of the object has to be a number for the cast exception to occure - object o = new {p = 1}; + object o = new { p = 1 }; var json = JObject.FromObject(o); @@ -5386,9 +5406,9 @@ To fix this error either change the environment to be fully trusted, change the ExceptionAssert.Throws( "Cannot convert null value to KeyValuePair. Path '[0]', line 1, position 6.", () => - { - JsonConvert.DeserializeObject>>>(json); - }); + { + JsonConvert.DeserializeObject>>>(json); + }); } [Test] @@ -5416,7 +5436,7 @@ To fix this error either change the environment to be fully trusted, change the [Test] public void DeserializeByteArrayWithTypeNameHandling() { - TestObject test = new TestObject("Test", new byte[] {72, 63, 62, 71, 92, 55}); + TestObject test = new TestObject("Test", new byte[] { 72, 63, 62, 71, 92, 55 }); JsonSerializer serializer = new JsonSerializer(); serializer.TypeNameHandling = TypeNameHandling.All; @@ -5435,10 +5455,10 @@ To fix this error either change the environment to be fully trusted, change the using (JsonReader bsonReader = new JsonTextReader(new StreamReader(bsonStream))) { // Get exception here - TestObject newObject = (TestObject) serializer.Deserialize(bsonReader); + TestObject newObject = (TestObject)serializer.Deserialize(bsonReader); Assert.AreEqual("Test", newObject.Name); - CollectionAssert.AreEquivalent(new byte[] {72, 63, 62, 71, 92, 55}, newObject.Data); + CollectionAssert.AreEquivalent(new byte[] { 72, 63, 62, 71, 92, 55 }, newObject.Data); } } @@ -5473,7 +5493,7 @@ To fix this error either change the environment to be fully trusted, change the [Test] public void ReadForTypeHackFixDecimal() { - IList d1 = new List {1.1m}; + IList d1 = new List { 1.1m }; string json = JsonConvert.SerializeObject(d1); @@ -5486,7 +5506,7 @@ To fix this error either change the environment to be fully trusted, change the [Test] public void ReadForTypeHackFixDateTimeOffset() { - IList d1 = new List {null}; + IList d1 = new List { null }; string json = JsonConvert.SerializeObject(d1); @@ -5499,7 +5519,7 @@ To fix this error either change the environment to be fully trusted, change the [Test] public void ReadForTypeHackFixByteArray() { - IList d1 = new List {null}; + IList d1 = new List { null }; string json = JsonConvert.SerializeObject(d1); @@ -5539,15 +5559,15 @@ To fix this error either change the environment to be fully trusted, change the ExceptionAssert.Throws( "Error converting value {null} to type 'System.Int32'. Path '[3]', line 5, position 7.", () => - { - List numbers = JsonConvert.DeserializeObject>(json); - }); + { + List numbers = JsonConvert.DeserializeObject>(json); + }); } [Test] public void SerializeNullableWidgetStruct() { - Widget widget = new Widget {Id = new WidgetId {Value = "id"}}; + Widget widget = new Widget { Id = new WidgetId { Value = "id" } }; string json = JsonConvert.SerializeObject(widget); @@ -5561,8 +5581,8 @@ To fix this error either change the environment to be fully trusted, change the Widget w = JsonConvert.DeserializeObject(json); - Assert.AreEqual(new WidgetId {Value = "id"}, w.Id); - Assert.AreEqual(new WidgetId {Value = "id"}, w.Id.Value); + Assert.AreEqual(new WidgetId { Value = "id" }, w.Id); + Assert.AreEqual(new WidgetId { Value = "id" }, w.Id.Value); Assert.AreEqual("id", w.Id.Value.Value); } @@ -5572,14 +5592,14 @@ To fix this error either change the environment to be fully trusted, change the ExceptionAssert.Throws( "Error reading integer. Unexpected token: Boolean. Path 'PreProperty', line 2, position 22.", () => - { - string json = @"{ + { + string json = @"{ ""PreProperty"": true, ""PostProperty"": ""-1"" }"; - JsonConvert.DeserializeObject(json); - }); + JsonConvert.DeserializeObject(json); + }); } [Test] @@ -5588,12 +5608,12 @@ To fix this error either change the environment to be fully trusted, change the ExceptionAssert.Throws( "Unexpected end when setting PreProperty's value. Path 'PreProperty', line 2, position 18.", () => - { - string json = @"{ + { + string json = @"{ ""PreProperty"": "; - JsonConvert.DeserializeObject(json); - }); + JsonConvert.DeserializeObject(json); + }); } [Test] @@ -5620,7 +5640,7 @@ To fix this error either change the environment to be fully trusted, change the Latitude = 33.657145, Longitude = -117.766684, TimeStamp = new DateTime(2000, 3, 1, 23, 59, 59, DateTimeKind.Utc), - Payload = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + Payload = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }; string jsonString = JsonConvert.SerializeObject(expected, Formatting.Indented); @@ -5686,13 +5706,13 @@ To fix this error either change the environment to be fully trusted, change the [Test] public void NullableStructWithConverter() { - string json = JsonConvert.SerializeObject(new Widget1 {Id = new WidgetId1 {Value = 1234}}); + string json = JsonConvert.SerializeObject(new Widget1 { Id = new WidgetId1 { Value = 1234 } }); Assert.AreEqual(@"{""Id"":""1234""}", json); Widget1 w = JsonConvert.DeserializeObject(@"{""Id"":""1234""}"); - Assert.AreEqual(new WidgetId1 {Value = 1234}, w.Id); + Assert.AreEqual(new WidgetId1 { Value = 1234 }, w.Id); } [Test] @@ -5765,9 +5785,9 @@ To fix this error either change the environment to be fully trusted, change the ExceptionAssert.Throws( "No JSON content found and type 'System.Int32' is not nullable. Path '', line 0, position 0.", () => - { - JsonConvert.DeserializeObject(""); - }); + { + JsonConvert.DeserializeObject(""); + }); } [Test] @@ -5784,9 +5804,9 @@ To fix this error either change the environment to be fully trusted, change the @"Value cannot be null. Parameter name: value", () => - { - JsonConvert.DeserializeObject(null); - }); + { + JsonConvert.DeserializeObject(null); + }); } [Test] @@ -5891,7 +5911,7 @@ Parameter name: value", product.Name = "Apple"; product.ExpiryDate = new DateTime(2012, 4, 1); product.Price = 3.99M; - product.Sizes = new []{"Small", "Medium", "Large"}; + product.Sizes = new[] { "Small", "Medium", "Large" }; string json = JsonConvert.SerializeObject(product); //{ @@ -5924,7 +5944,7 @@ Parameter name: value", // ":::SIZES:::": [ ":::SMALL:::", ":::MEDIUM:::", ":::LARGE:::" ] //} - Color[] colors = new []{ Color.Blue, Color.Red, Color.Yellow, Color.Green, Color.Black, Color.Brown }; + Color[] colors = new[] { Color.Blue, Color.Red, Color.Yellow, Color.Green, Color.Black, Color.Brown }; string json2 = JsonConvert.SerializeObject(colors, new JsonSerializerSettings { @@ -5932,7 +5952,7 @@ Parameter name: value", Converters = { new MetroStringConverter(), new MetroColorConverter() }, Formatting = Formatting.Indented }); - + Assert.AreEqual(@"[ "":::GRAY:::"", "":::GRAY:::"", @@ -5943,37 +5963,11 @@ Parameter name: value", ]", json2); } - public class MetroStringConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteValue(":::" + value.ToString().ToUpper(CultureInfo.InvariantCulture) + ":::"); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - return existingValue; - } - - public override bool CanConvert(Type objectType) - { - return objectType == typeof (string); - } - } - - public class MetroPropertyNameResolver : DefaultContractResolver - { - protected internal override string ResolvePropertyName(string propertyName) - { - return ":::" + propertyName.ToUpper(CultureInfo.InvariantCulture) + ":::"; - } - } - public class MetroColorConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - Color color = (Color) value; + Color color = (Color)value; Color fixedColor = (color == Color.White || color == Color.Black) ? color : Color.Gray; writer.WriteValue(":::" + fixedColor.ToKnownColor().ToString().ToUpper() + ":::"); @@ -5981,12 +5975,12 @@ Parameter name: value", public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - return Enum.Parse(typeof (Color), reader.Value.ToString()); + return Enum.Parse(typeof(Color), reader.Value.ToString()); } public override bool CanConvert(Type objectType) { - return objectType == typeof (Color); + return objectType == typeof(Color); } } #endif @@ -6093,6 +6087,58 @@ Parameter name: value", Assert.AreEqual("Cannot write a null value for property 'UnsetProperty'. Property requires a value.", errors[1]); Assert.AreEqual("Cannot write a null value for property 'AlwaysProperty'. Property requires a value.", errors[2]); } + + [Test] + public void DeserializeCollectionItemConverter() + { + PropertyItemConverter c = new PropertyItemConverter + { + Data = + new[]{ + "one", + "two", + "three" + } + }; + + var c2 = JsonConvert.DeserializeObject("{'Data':['::ONE::','::TWO::']}"); + + Assert.IsNotNull(c2); + Assert.AreEqual(2, c2.Data.Count); + Assert.AreEqual("one", c2.Data[0]); + Assert.AreEqual("two", c2.Data[1]); + } + + [Test] + public void SerializeCollectionItemConverter() + { + PropertyItemConverter c = new PropertyItemConverter + { + Data = new[] + { + "one", + "two", + "three" + } + }; + + string json = JsonConvert.SerializeObject(c); + + Assert.AreEqual(@"{""Data"":["":::ONE:::"","":::TWO:::"","":::THREE:::""]}", json); + } + + [Test] + public void DeserializeEmptyJsonString() + { + string s = (string) new JsonSerializer().Deserialize(new JsonTextReader(new StringReader("''"))); + Assert.AreEqual("", s); + } + } + + public class PropertyItemConverter + { + [JsonProperty(ItemConverterType = typeof(MetroStringConverter))] + public IList Data { get; set; } } public class PersonWithPrivateConstructor @@ -6295,4 +6341,34 @@ Parameter name: value", [JsonProperty(Required = Required.Always)] public int? AlwaysProperty { get; set; } } + + public class MetroStringConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(":::" + value.ToString().ToUpper(CultureInfo.InvariantCulture) + ":::"); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + string s = (string)reader.Value; + if (s == null) + return null; + + return s.ToLower(CultureInfo.InvariantCulture).Trim(new[] { ':' }); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(string); + } + } + + public class MetroPropertyNameResolver : DefaultContractResolver + { + protected internal override string ResolvePropertyName(string propertyName) + { + return ":::" + propertyName.ToUpper(CultureInfo.InvariantCulture) + ":::"; + } + } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs index 328b1ab3..ecae6093 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs @@ -1006,6 +1006,74 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.IsTrue(ReferenceEquals(referenceObject.Component1, referenceObject.Component2)); } + + [Test] + public void PropertyItemIsReferenceObject() + { + TestComponentSimple c1 = new TestComponentSimple(); + + PropertyItemIsReferenceObject o1 = new PropertyItemIsReferenceObject + { + Data = new PropertyItemIsReferenceBody + { + Prop1 = c1, + Prop2 = c1, + Data = new List + { + c1 + } + } + }; + + string json = JsonConvert.SerializeObject(o1, Formatting.Indented); + Assert.AreEqual(@"{ + ""Data"": { + ""Prop1"": { + ""$id"": ""1"", + ""MyProperty"": 0 + }, + ""Prop2"": { + ""$ref"": ""1"" + }, + ""Data"": { + ""$id"": ""2"", + ""$values"": [ + { + ""MyProperty"": 0 + } + ] + } + } +}", json); + + PropertyItemIsReferenceObject o2 = JsonConvert.DeserializeObject(json); + + TestComponentSimple c2 = o2.Data.Prop1; + TestComponentSimple c3 = o2.Data.Prop2; + TestComponentSimple c4 = o2.Data.Data[0]; + + Assert.IsTrue(ReferenceEquals(c2, c3)); + Assert.IsFalse(ReferenceEquals(c2, c4)); + } + } + + public class PropertyItemIsReferenceBody + { + public TestComponentSimple Prop1 { get; set; } + public TestComponentSimple Prop2 { get; set; } + public IList Data { get; set; } + } + + public class PropertyItemIsReferenceObject + { + [JsonProperty(ItemIsReference = true)] + public PropertyItemIsReferenceBody Data { get; set; } + } + + public class PropertyItemIsReferenceList + { + [JsonProperty(ItemIsReference = true)] + public IList> Data { get; set; } } [JsonArray(ItemIsReference = true)] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/ReferenceLoopHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/ReferenceLoopHandlingTests.cs index 9282e51b..488b9f0f 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/ReferenceLoopHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/ReferenceLoopHandlingTests.cs @@ -112,6 +112,62 @@ namespace Newtonsoft.Json.Tests.Serialization }); Assert.AreEqual("{}", json); } + + [Test] + public void SerializePropertyItemReferenceLoopHandling() + { + PropertyItemReferenceLoopHandling c = new PropertyItemReferenceLoopHandling(); + c.Text = "Text!"; + c.SetData(new List { c }); + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Text"": ""Text!"", + ""Data"": [ + { + ""Text"": ""Text!"", + ""Data"": [ + { + ""Text"": ""Text!"", + ""Data"": [ + { + ""Text"": ""Text!"", + ""Data"": null + } + ] + } + ] + } + ] +}", json); + } + } + + public class PropertyItemReferenceLoopHandling + { + private IList _data; + private int _accessCount; + + public string Text { get; set; } + + [JsonProperty(ItemReferenceLoopHandling = ReferenceLoopHandling.Serialize)] + public IList Data + { + get + { + if (_accessCount >= 3) + return null; + + _accessCount++; + return new List(_data); + } + } + + public void SetData(IList data) + { + _data = data; + } } [JsonArray(ItemReferenceLoopHandling = ReferenceLoopHandling.Ignore)] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs index 565d2fd2..00f04c93 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs @@ -24,6 +24,10 @@ #endregion #if !PORTABLE +#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) +using System.Dynamic; +#endif +using Newtonsoft.Json.Tests.Linq; using global::System; using global::System.Collections; using global::System.Collections.Generic; @@ -65,13 +69,13 @@ namespace Newtonsoft.Json.Tests.Serialization }; wrapper.Dictionary = new Dictionary { - { "First", new EmployeeReference() } + {"First", new EmployeeReference()} }; string json = JsonConvert.SerializeObject(wrapper, Formatting.Indented, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Auto - }); + { + TypeNameHandling = TypeNameHandling.Auto + }); Assert.AreEqual(@"{ ""Array"": [ @@ -91,21 +95,21 @@ namespace Newtonsoft.Json.Tests.Serialization }", json); Wrapper w2 = JsonConvert.DeserializeObject(json); - CustomAssert.IsInstanceOfType(typeof(List), w2.Array); - CustomAssert.IsInstanceOfType(typeof(Dictionary), w2.Dictionary); + CustomAssert.IsInstanceOfType(typeof (List), w2.Array); + CustomAssert.IsInstanceOfType(typeof (Dictionary), w2.Dictionary); } [Test] public void WriteTypeNameForObjects() { - string employeeRef = ReflectionUtils.GetTypeName(typeof(EmployeeReference), FormatterAssemblyStyle.Simple); + string employeeRef = ReflectionUtils.GetTypeName(typeof (EmployeeReference), FormatterAssemblyStyle.Simple); EmployeeReference employee = new EmployeeReference(); string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects - }); + { + TypeNameHandling = TypeNameHandling.Objects + }); Assert.AreEqual(@"{ ""$id"": ""1"", @@ -118,7 +122,7 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void DeserializeTypeName() { - string employeeRef = ReflectionUtils.GetTypeName(typeof(EmployeeReference), FormatterAssemblyStyle.Simple); + string employeeRef = ReflectionUtils.GetTypeName(typeof (EmployeeReference), FormatterAssemblyStyle.Simple); string json = @"{ ""$id"": ""1"", @@ -128,19 +132,19 @@ namespace Newtonsoft.Json.Tests.Serialization }"; object employee = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects - }); + { + TypeNameHandling = TypeNameHandling.Objects + }); - CustomAssert.IsInstanceOfType(typeof(EmployeeReference), employee); - Assert.AreEqual("Name!", ((EmployeeReference)employee).Name); + CustomAssert.IsInstanceOfType(typeof (EmployeeReference), employee); + Assert.AreEqual("Name!", ((EmployeeReference) employee).Name); } #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) [Test] public void DeserializeTypeNameFromGacAssembly() { - string cookieRef = ReflectionUtils.GetTypeName(typeof(Cookie), FormatterAssemblyStyle.Simple); + string cookieRef = ReflectionUtils.GetTypeName(typeof (Cookie), FormatterAssemblyStyle.Simple); string json = @"{ ""$id"": ""1"", @@ -148,19 +152,19 @@ namespace Newtonsoft.Json.Tests.Serialization }"; object cookie = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects - }); + { + TypeNameHandling = TypeNameHandling.Objects + }); - CustomAssert.IsInstanceOfType(typeof(Cookie), cookie); + CustomAssert.IsInstanceOfType(typeof (Cookie), cookie); } #endif [Test] public void SerializeGenericObjectListWithTypeName() { - string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName; - string personRef = typeof(Person).AssemblyQualifiedName; + string employeeRef = typeof (EmployeeReference).AssemblyQualifiedName; + string personRef = typeof (Person).AssemblyQualifiedName; List values = new List { @@ -180,10 +184,10 @@ namespace Newtonsoft.Json.Tests.Serialization }; string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Full - }); + { + TypeNameHandling = TypeNameHandling.Objects, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Full + }); Assert.AreEqual(@"[ { @@ -211,8 +215,8 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void DeserializeGenericObjectListWithTypeName() { - string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName; - string personRef = typeof(Person).AssemblyQualifiedName; + string employeeRef = typeof (EmployeeReference).AssemblyQualifiedName; + string personRef = typeof (Person).AssemblyQualifiedName; string json = @"[ { @@ -236,16 +240,16 @@ namespace Newtonsoft.Json.Tests.Serialization -2147483648 ]"; - List values = (List)JsonConvert.DeserializeObject(json, typeof(List), new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Full - }); + List values = (List) JsonConvert.DeserializeObject(json, typeof (List), new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Full + }); Assert.AreEqual(4, values.Count); - EmployeeReference e = (EmployeeReference)values[0]; - Person p = (Person)values[1]; + EmployeeReference e = (EmployeeReference) values[0]; + Person p = (Person) values[1]; Assert.AreEqual("Bob", e.Name); Assert.AreEqual("Frank", e.Manager.Name); @@ -255,14 +259,14 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.AreEqual(new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), p.LastModified); Assert.AreEqual("String!", values[2]); - Assert.AreEqual((long)int.MinValue, values[3]); + Assert.AreEqual((long) int.MinValue, values[3]); } [Test] public void DeserializeWithBadTypeName() { - string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName; - string personRef = typeof(Person).AssemblyQualifiedName; + string employeeRef = typeof (EmployeeReference).AssemblyQualifiedName; + string personRef = typeof (Person).AssemblyQualifiedName; string json = @"{ ""$id"": ""1"", @@ -273,11 +277,11 @@ namespace Newtonsoft.Json.Tests.Serialization try { - JsonConvert.DeserializeObject(json, typeof(Person), new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Full - }); + JsonConvert.DeserializeObject(json, typeof (Person), new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Full + }); } catch (JsonSerializationException ex) { @@ -288,7 +292,7 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void DeserializeTypeNameWithNoTypeNameHandling() { - string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName; + string employeeRef = typeof (EmployeeReference).AssemblyQualifiedName; string json = @"{ ""$id"": ""1"", @@ -297,7 +301,7 @@ namespace Newtonsoft.Json.Tests.Serialization ""Manager"": null }"; - JObject o = (JObject)JsonConvert.DeserializeObject(json); + JObject o = (JObject) JsonConvert.DeserializeObject(json); Assert.AreEqual(@"{ ""Name"": ""Name!"", @@ -318,12 +322,12 @@ namespace Newtonsoft.Json.Tests.Serialization ExceptionAssert.Throws( "Type specified in JSON 'Newtonsoft.Json.Tests.TestObjects.Employee' was not resolved. Path '$type', line 3, position 56.", () => - { - JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings { - TypeNameHandling = TypeNameHandling.Objects + JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); }); - }); } public interface ICorrelatedMessage @@ -338,6 +342,7 @@ namespace Newtonsoft.Json.Tests.Serialization RequestEncoding = "UTF-8"; Method = "GET"; } + public string Method { get; set; } public Dictionary Headers { get; set; } public string Url { get; set; } @@ -352,7 +357,7 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void DeserializeGenericTypeName() { - string typeName = typeof(SendHttpRequest).AssemblyQualifiedName; + string typeName = typeof (SendHttpRequest).AssemblyQualifiedName; string json = @"{ ""$type"": """ + typeName + @""", @@ -368,14 +373,14 @@ namespace Newtonsoft.Json.Tests.Serialization }"; ICorrelatedMessage message = JsonConvert.DeserializeObject(json, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Full - }); + { + TypeNameHandling = TypeNameHandling.Objects, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Full + }); - CustomAssert.IsInstanceOfType(typeof(SendHttpRequest), message); + CustomAssert.IsInstanceOfType(typeof (SendHttpRequest), message); - SendHttpRequest request = (SendHttpRequest)message; + SendHttpRequest request = (SendHttpRequest) message; Assert.AreEqual("xyz", request.CorrelationId); Assert.AreEqual(2, request.RequestData.Count); Assert.AreEqual("siedemnaście", request.RequestData["Id"]); @@ -384,22 +389,22 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void SerializeObjectWithMultipleGenericLists() { - string containerTypeName = typeof(Container).AssemblyQualifiedName; - string productListTypeName = typeof(List).AssemblyQualifiedName; + string containerTypeName = typeof (Container).AssemblyQualifiedName; + string productListTypeName = typeof (List).AssemblyQualifiedName; Container container = new Container - { - In = new List(), - Out = new List() - }; + { + In = new List(), + Out = new List() + }; string json = JsonConvert.SerializeObject(container, Formatting.Indented, - new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore, - TypeNameHandling = TypeNameHandling.All, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Full - }); + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.All, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Full + }); Assert.AreEqual(@"{ ""$type"": """ + containerTypeName + @""", @@ -417,6 +422,7 @@ namespace Newtonsoft.Json.Tests.Serialization public class TypeNameProperty { public string Name { get; set; } + [JsonProperty(TypeNameHandling = TypeNameHandling.All)] public object Value { get; set; } } @@ -424,16 +430,16 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void WriteObjectTypeNameForProperty() { - string typeNamePropertyRef = ReflectionUtils.GetTypeName(typeof(TypeNameProperty), FormatterAssemblyStyle.Simple); + string typeNamePropertyRef = ReflectionUtils.GetTypeName(typeof (TypeNameProperty), FormatterAssemblyStyle.Simple); TypeNameProperty typeNameProperty = new TypeNameProperty - { - Name = "Name!", - Value = new TypeNameProperty { - Name = "Nested!" - } - }; + Name = "Name!", + Value = new TypeNameProperty + { + Name = "Nested!" + } + }; string json = JsonConvert.SerializeObject(typeNameProperty, Formatting.Indented); @@ -448,9 +454,9 @@ namespace Newtonsoft.Json.Tests.Serialization TypeNameProperty deserialized = JsonConvert.DeserializeObject(json); Assert.AreEqual("Name!", deserialized.Name); - CustomAssert.IsInstanceOfType(typeof(TypeNameProperty), deserialized.Value); + CustomAssert.IsInstanceOfType(typeof (TypeNameProperty), deserialized.Value); - TypeNameProperty nested = (TypeNameProperty)deserialized.Value; + TypeNameProperty nested = (TypeNameProperty) deserialized.Value; Assert.AreEqual("Nested!", nested.Name); Assert.AreEqual(null, nested.Value); } @@ -458,13 +464,13 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void WriteListTypeNameForProperty() { - string listRef = ReflectionUtils.GetTypeName(typeof(List), FormatterAssemblyStyle.Simple); + string listRef = ReflectionUtils.GetTypeName(typeof (List), FormatterAssemblyStyle.Simple); TypeNameProperty typeNameProperty = new TypeNameProperty - { - Name = "Name!", - Value = new List { 1, 2, 3, 4, 5 } - }; + { + Name = "Name!", + Value = new List {1, 2, 3, 4, 5} + }; string json = JsonConvert.SerializeObject(typeNameProperty, Formatting.Indented); @@ -484,9 +490,9 @@ namespace Newtonsoft.Json.Tests.Serialization TypeNameProperty deserialized = JsonConvert.DeserializeObject(json); Assert.AreEqual("Name!", deserialized.Name); - CustomAssert.IsInstanceOfType(typeof(List), deserialized.Value); + CustomAssert.IsInstanceOfType(typeof (List), deserialized.Value); - List nested = (List)deserialized.Value; + List nested = (List) deserialized.Value; Assert.AreEqual(5, nested.Count); Assert.AreEqual(1, nested[0]); Assert.AreEqual(2, nested[1]); @@ -505,14 +511,14 @@ namespace Newtonsoft.Json.Tests.Serialization }"; object p = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Objects, - Binder = new CustomSerializationBinder() - }); + { + TypeNameHandling = TypeNameHandling.Objects, + Binder = new CustomSerializationBinder() + }); - CustomAssert.IsInstanceOfType(typeof(Person), p); + CustomAssert.IsInstanceOfType(typeof (Person), p); - Person person = (Person)p; + Person person = (Person) p; Assert.AreEqual("Name!", person.Name); } @@ -521,7 +527,7 @@ namespace Newtonsoft.Json.Tests.Serialization { public override Type BindToType(string assemblyName, string typeName) { - return typeof(Person); + return typeof (Person); } } @@ -546,10 +552,10 @@ namespace Newtonsoft.Json.Tests.Serialization }; string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Auto, - Binder = binder - }); + { + TypeNameHandling = TypeNameHandling.Auto, + Binder = binder + }); //[ // { @@ -579,17 +585,17 @@ namespace Newtonsoft.Json.Tests.Serialization ]", json); IList newValues = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.Auto, - Binder = new TypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests") - }); + { + TypeNameHandling = TypeNameHandling.Auto, + Binder = new TypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests") + }); - CustomAssert.IsInstanceOfType(typeof(Customer), newValues[0]); - Customer customer = (Customer)newValues[0]; + CustomAssert.IsInstanceOfType(typeof (Customer), newValues[0]); + Customer customer = (Customer) newValues[0]; Assert.AreEqual("Caroline Customer", customer.Name); - CustomAssert.IsInstanceOfType(typeof(Purchase), newValues[1]); - Purchase purchase = (Purchase)newValues[1]; + CustomAssert.IsInstanceOfType(typeof (Purchase), newValues[1]); + Purchase purchase = (Purchase) newValues[1]; Assert.AreEqual("Elbow Grease", purchase.ProductName); } @@ -640,9 +646,9 @@ namespace Newtonsoft.Json.Tests.Serialization string json = sw.ToString(); - string contentSubClassRef = ReflectionUtils.GetTypeName(typeof(ContentSubClass), FormatterAssemblyStyle.Simple); - string dictionaryRef = ReflectionUtils.GetTypeName(typeof(Dictionary>), FormatterAssemblyStyle.Simple); - string listRef = ReflectionUtils.GetTypeName(typeof(List), FormatterAssemblyStyle.Simple); + string contentSubClassRef = ReflectionUtils.GetTypeName(typeof (ContentSubClass), FormatterAssemblyStyle.Simple); + string dictionaryRef = ReflectionUtils.GetTypeName(typeof (Dictionary>), FormatterAssemblyStyle.Simple); + string listRef = ReflectionUtils.GetTypeName(typeof (List), FormatterAssemblyStyle.Simple); string expected = @"{ ""TestMember"": { @@ -680,15 +686,15 @@ namespace Newtonsoft.Json.Tests.Serialization } Assert.IsNotNull(anotherTestObject); - CustomAssert.IsInstanceOfType(typeof(ContentSubClass), anotherTestObject.TestMember); - CustomAssert.IsInstanceOfType(typeof(Dictionary>), anotherTestObject.AnotherTestMember); + CustomAssert.IsInstanceOfType(typeof (ContentSubClass), anotherTestObject.TestMember); + CustomAssert.IsInstanceOfType(typeof (Dictionary>), anotherTestObject.AnotherTestMember); Assert.AreEqual(1, anotherTestObject.AnotherTestMember.Count); IList list = anotherTestObject.AnotherTestMember[1]; - CustomAssert.IsInstanceOfType(typeof(List), list); + CustomAssert.IsInstanceOfType(typeof (List), list); Assert.AreEqual(1, list.Count); - CustomAssert.IsInstanceOfType(typeof(ContentSubClass), list[0]); + CustomAssert.IsInstanceOfType(typeof (ContentSubClass), list[0]); } [Test] @@ -697,10 +703,10 @@ namespace Newtonsoft.Json.Tests.Serialization Message message = new Message(); message.Address = "http://www.google.com"; message.Body = new SearchDetails - { - Query = "Json.NET", - Language = "en-us" - }; + { + Query = "Json.NET", + Language = "en-us" + }; string json = JsonConvert.SerializeObject(message, Formatting.Indented); // { @@ -714,7 +720,7 @@ namespace Newtonsoft.Json.Tests.Serialization Message deserialized = JsonConvert.DeserializeObject(json); - SearchDetails searchDetails = (SearchDetails)deserialized.Body; + SearchDetails searchDetails = (SearchDetails) deserialized.Body; // Json.NET } @@ -730,23 +736,24 @@ namespace Newtonsoft.Json.Tests.Serialization { Dictionary collection = new Dictionary() { - {"First", new UrlStatus{ Status = 404, Url = @"http://www.bing.com"}}, - {"Second", new UrlStatus{Status = 400, Url = @"http://www.google.com"}}, - {"List", new List - { - new UrlStatus {Status = 300, Url = @"http://www.yahoo.com"}, - new UrlStatus {Status = 200, Url = @"http://www.askjeeves.com"} + {"First", new UrlStatus {Status = 404, Url = @"http://www.bing.com"}}, + {"Second", new UrlStatus {Status = 400, Url = @"http://www.google.com"}}, + { + "List", new List + { + new UrlStatus {Status = 300, Url = @"http://www.yahoo.com"}, + new UrlStatus {Status = 200, Url = @"http://www.askjeeves.com"} + } } - } }; string json = JsonConvert.SerializeObject(collection, Formatting.Indented, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.All, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple - }); + { + TypeNameHandling = TypeNameHandling.All, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple + }); - string urlStatusTypeName = ReflectionUtils.GetTypeName(typeof(UrlStatus), FormatterAssemblyStyle.Simple); + string urlStatusTypeName = ReflectionUtils.GetTypeName(typeof (UrlStatus), FormatterAssemblyStyle.Simple); Assert.AreEqual(@"{ ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"", @@ -778,18 +785,18 @@ namespace Newtonsoft.Json.Tests.Serialization }", json); object c = JsonConvert.DeserializeObject(json, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.All, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple - }); + { + TypeNameHandling = TypeNameHandling.All, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple + }); - CustomAssert.IsInstanceOfType(typeof(Dictionary), c); + CustomAssert.IsInstanceOfType(typeof (Dictionary), c); - Dictionary newCollection = (Dictionary)c; + Dictionary newCollection = (Dictionary) c; Assert.AreEqual(3, newCollection.Count); - Assert.AreEqual(@"http://www.bing.com", ((UrlStatus)newCollection["First"]).Url); + Assert.AreEqual(@"http://www.bing.com", ((UrlStatus) newCollection["First"]).Url); - List statues = (List)newCollection["List"]; + List statues = (List) newCollection["List"]; Assert.AreEqual(2, statues.Count); } @@ -797,11 +804,11 @@ namespace Newtonsoft.Json.Tests.Serialization [Test] public void SerializingIEnumerableOfTShouldRetainGenericTypeInfo() { - string productClassRef = ReflectionUtils.GetTypeName(typeof(Product[]), FormatterAssemblyStyle.Simple); + string productClassRef = ReflectionUtils.GetTypeName(typeof (Product[]), FormatterAssemblyStyle.Simple); CustomEnumerable products = new CustomEnumerable(); - string json = JsonConvert.SerializeObject(products, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }); + string json = JsonConvert.SerializeObject(products, Formatting.Indented, new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All}); Assert.AreEqual(@"{ ""$type"": """ + productClassRef + @""", @@ -872,8 +879,8 @@ namespace Newtonsoft.Json.Tests.Serialization { Car testerObject = new Car(); testerObject.Year = new DateTime(2000, 10, 5, 1, 1, 1, DateTimeKind.Utc); - byte[] data = new byte[] { 75, 65, 82, 73, 82, 65 }; - testerObject.Objects = new object[] { data, "prueba" }; + byte[] data = new byte[] {75, 65, 82, 73, 82, 65}; + testerObject.Objects = new object[] {data, "prueba"}; JsonSerializerSettings jsonSettings = new JsonSerializerSettings(); jsonSettings.NullValueHandling = NullValueHandling.Ignore; @@ -881,7 +888,7 @@ namespace Newtonsoft.Json.Tests.Serialization string output = JsonConvert.SerializeObject(testerObject, Formatting.Indented, jsonSettings); - string carClassRef = ReflectionUtils.GetTypeName(typeof(Car), FormatterAssemblyStyle.Simple); + string carClassRef = ReflectionUtils.GetTypeName(typeof (Car), FormatterAssemblyStyle.Simple); Assert.AreEqual(output, @"{ ""$type"": """ + carClassRef + @""", @@ -903,7 +910,7 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.IsTrue(obj.Objects[0] is byte[]); - byte[] d = (byte[])obj.Objects[0]; + byte[] d = (byte[]) obj.Objects[0]; CollectionAssert.AreEquivalent(data, d); } @@ -915,9 +922,9 @@ namespace Newtonsoft.Json.Tests.Serialization IExample e = new Example("Rob"); SerializableWrapper w = new SerializableWrapper - { - Content = e - }; + { + Content = e + }; //Test Binary Serialization Round Trip //This will work find because the Binary Formatter serializes type names @@ -961,23 +968,23 @@ namespace Newtonsoft.Json.Tests.Serialization public void SerializationBinderWithFullName() { Message message = new Message - { - Address = "jamesnk@testtown.com", - Body = new Version(1, 2, 3, 4) - }; + { + Address = "jamesnk@testtown.com", + Body = new Version(1, 2, 3, 4) + }; string json = JsonConvert.SerializeObject(message, Formatting.Indented, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.All, - TypeNameAssemblyFormat = FormatterAssemblyStyle.Full, - Binder = new MetroBinder(), - ContractResolver = new DefaultContractResolver { + TypeNameHandling = TypeNameHandling.All, + TypeNameAssemblyFormat = FormatterAssemblyStyle.Full, + Binder = new MetroBinder(), + ContractResolver = new DefaultContractResolver + { #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) IgnoreSerializableAttribute = true #endif - } - }); + } + }); Assert.AreEqual(@"{ ""$type"": "":::MESSAGE:::, AssemblyName"", @@ -1037,10 +1044,10 @@ namespace Newtonsoft.Json.Tests.Serialization TypeNameList l = new TypeNameList(); l.Add(c1); l.Add(new Employee - { - BirthDate = new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc), - Department = "Department!" - }); + { + BirthDate = new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc), + Department = "Department!" + }); l.Add("String!"); l.Add(long.MaxValue); @@ -1065,17 +1072,17 @@ namespace Newtonsoft.Json.Tests.Serialization TypeNameList l2 = JsonConvert.DeserializeObject>(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]); + 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 l = new TypeNameDictionary(); - l.Add("First", new TestComponentSimple { MyProperty = 1 }); + l.Add("First", new TestComponentSimple {MyProperty = 1}); l.Add("Second", "String!"); l.Add("Third", long.MaxValue); @@ -1092,10 +1099,10 @@ namespace Newtonsoft.Json.Tests.Serialization TypeNameDictionary l2 = JsonConvert.DeserializeObject>(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"]); + 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] @@ -1103,9 +1110,9 @@ namespace Newtonsoft.Json.Tests.Serialization { TypeNameObject o1 = new TypeNameObject(); - o1.Object1 = new TestComponentSimple { MyProperty = 1 }; + o1.Object1 = new TestComponentSimple {MyProperty = 1}; o1.Object2 = 123; - o1.ObjectNotHandled = new TestComponentSimple { MyProperty = int.MaxValue }; + o1.ObjectNotHandled = new TestComponentSimple {MyProperty = int.MaxValue}; o1.String = "String!"; o1.Integer = int.MaxValue; @@ -1127,14 +1134,327 @@ namespace Newtonsoft.Json.Tests.Serialization TypeNameObject o2 = JsonConvert.DeserializeObject(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); + 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()); } + + [Test] + public void PropertyItemTypeNameHandling() + { + PropertyItemTypeNameHandling c1 = new PropertyItemTypeNameHandling(); + c1.Data = new List + { + 1, + "two", + new TestComponentSimple {MyProperty = 1} + }; + + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + Assert.AreEqual(@"{ + ""Data"": [ + 1, + ""two"", + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + } + ] +}", json); + + PropertyItemTypeNameHandling c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(3, c2.Data.Count); + + CustomAssert.IsInstanceOfType(typeof (long), c2.Data[0]); + CustomAssert.IsInstanceOfType(typeof (string), c2.Data[1]); + CustomAssert.IsInstanceOfType(typeof (TestComponentSimple), c2.Data[2]); + TestComponentSimple c = (TestComponentSimple) c2.Data[2]; + Assert.AreEqual(1, c.MyProperty); + } + + [Test] + public void PropertyItemTypeNameHandlingNestedCollections() + { + PropertyItemTypeNameHandling c1 = new PropertyItemTypeNameHandling + { + Data = new List + { + new TestComponentSimple {MyProperty = 1}, + new List + { + new List + { + new List() + } + } + } + }; + + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + Assert.AreEqual(@"{ + ""Data"": [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + }, + { + ""$type"": ""System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib"", + ""$values"": [ + [ + [] + ] + ] + } + ] +}", json); + + PropertyItemTypeNameHandling c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(2, c2.Data.Count); + + CustomAssert.IsInstanceOfType(typeof (TestComponentSimple), c2.Data[0]); + CustomAssert.IsInstanceOfType(typeof (List), c2.Data[1]); + List c = (List) c2.Data[1]; + CustomAssert.IsInstanceOfType(typeof (JArray), c[0]); + + json = @"{ + ""Data"": [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + }, + { + ""$type"": ""System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib"", + ""$values"": [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + } + ] + } + ] +}"; + + c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(2, c2.Data.Count); + + CustomAssert.IsInstanceOfType(typeof (TestComponentSimple), c2.Data[0]); + CustomAssert.IsInstanceOfType(typeof (List), c2.Data[1]); + c = (List) c2.Data[1]; + CustomAssert.IsInstanceOfType(typeof (JObject), c[0]); + JObject o = (JObject) c[0]; + Assert.AreEqual(1, (int) o["MyProperty"]); + } + + [Test] + public void PropertyItemTypeNameHandlingNestedDictionaries() + { + PropertyItemTypeNameHandlingDictionary c1 = new PropertyItemTypeNameHandlingDictionary() + { + Data = new Dictionary + { + { + "one", new TestComponentSimple {MyProperty = 1} + }, + { + "two", new Dictionary + { + { + "one", new Dictionary + { + {"one", 1} + } + } + } + } + } + }; + + string json = JsonConvert.SerializeObject(c1, Formatting.Indented); + Assert.AreEqual(@"{ + ""Data"": { + ""one"": { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + }, + ""two"": { + ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"", + ""one"": { + ""one"": 1 + } + } + } +}", json); + + PropertyItemTypeNameHandlingDictionary c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(2, c2.Data.Count); + + CustomAssert.IsInstanceOfType(typeof (TestComponentSimple), c2.Data["one"]); + CustomAssert.IsInstanceOfType(typeof(Dictionary), c2.Data["two"]); + Dictionary c = (Dictionary)c2.Data["two"]; + CustomAssert.IsInstanceOfType(typeof (JObject), c["one"]); + + json = @"{ + ""Data"": { + ""one"": { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + }, + ""two"": { + ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"", + ""one"": { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + } + } + } +}"; + + c2 = JsonConvert.DeserializeObject(json); + Assert.AreEqual(2, c2.Data.Count); + + CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), c2.Data["one"]); + CustomAssert.IsInstanceOfType(typeof(Dictionary), c2.Data["two"]); + c = (Dictionary)c2.Data["two"]; + CustomAssert.IsInstanceOfType(typeof(JObject), c["one"]); + + JObject o = (JObject) c["one"]; + Assert.AreEqual(1, (int) o["MyProperty"]); + } + + [Test] + public void PropertyItemTypeNameHandlingObject() + { + PropertyItemTypeNameHandlingObject o1 = new PropertyItemTypeNameHandlingObject + { + Data = new TypeNameHandlingTestObject + { + Prop1 = new List + { + new TestComponentSimple + { + MyProperty = 1 + } + }, + Prop2 = new TestComponentSimple + { + MyProperty = 1 + }, + Prop3 = 3, + Prop4 = new JObject() + } + }; + + string json = JsonConvert.SerializeObject(o1, Formatting.Indented); + Assert.AreEqual(@"{ + ""Data"": { + ""Prop1"": { + ""$type"": ""System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib"", + ""$values"": [ + { + ""MyProperty"": 1 + } + ] + }, + ""Prop2"": { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + }, + ""Prop3"": 3, + ""Prop4"": {} + } +}", json); + + PropertyItemTypeNameHandlingObject o2 = JsonConvert.DeserializeObject(json); + Assert.IsNotNull(o2); + Assert.IsNotNull(o2.Data); + + CustomAssert.IsInstanceOfType(typeof(List), o2.Data.Prop1); + CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), o2.Data.Prop2); + CustomAssert.IsInstanceOfType(typeof(long), o2.Data.Prop3); + CustomAssert.IsInstanceOfType(typeof(JObject), o2.Data.Prop4); + + List o = (List)o2.Data.Prop1; + JObject j = (JObject)o[0]; + Assert.AreEqual(1, (int)j["MyProperty"]); + } + +#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) + [Test] + public void PropertyItemTypeNameHandlingDynamic() + { + PropertyItemTypeNameHandlingDynamic d1 = new PropertyItemTypeNameHandlingDynamic(); + + dynamic data = new DynamicDictionary(); + data.one = new TestComponentSimple + { + MyProperty = 1 + }; + + dynamic data2 = new DynamicDictionary(); + data2.one = new TestComponentSimple + { + MyProperty = 2 + }; + + data.two = data2; + + d1.Data = (DynamicDictionary)data; + + string json = JsonConvert.SerializeObject(d1, Formatting.Indented); + Assert.AreEqual(@"{ + ""Data"": { + ""one"": { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + }, + ""two"": { + ""$type"": ""Newtonsoft.Json.Tests.Linq.DynamicDictionary, Newtonsoft.Json.Tests"", + ""one"": { + ""MyProperty"": 2 + } + } + } +}", json); + + PropertyItemTypeNameHandlingDynamic d2 = JsonConvert.DeserializeObject(json); + Assert.IsNotNull(d2); + Assert.IsNotNull(d2.Data); + + dynamic data3 = d2.Data; + TestComponentSimple c = (TestComponentSimple)data3.one; + Assert.AreEqual(1, c.MyProperty); + + dynamic data4 = data3.two; + JObject o = (JObject)data4.one; + Assert.AreEqual(2, (int)o["MyProperty"]); + + json = @"{ + ""Data"": { + ""one"": { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 1 + }, + ""two"": { + ""$type"": ""Newtonsoft.Json.Tests.Linq.DynamicDictionary, Newtonsoft.Json.Tests"", + ""one"": { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.TestComponentSimple, Newtonsoft.Json.Tests"", + ""MyProperty"": 2 + } + } + } +}"; + + d2 = JsonConvert.DeserializeObject(json); + data3 = d2.Data; + data4 = data3.two; + o = (JObject)data4.one; + Assert.AreEqual(2, (int)o["MyProperty"]); + } +#endif } public class Message @@ -1225,6 +1545,40 @@ namespace Newtonsoft.Json.Tests.Serialization } #endif + public class PropertyItemTypeNameHandlingObject + { + [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)] + public TypeNameHandlingTestObject Data { get; set; } + } + +#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) + public class PropertyItemTypeNameHandlingDynamic + { + [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)] + public DynamicDictionary Data { get; set; } + } +#endif + + public class TypeNameHandlingTestObject + { + public object Prop1 { get; set; } + public object Prop2 { get; set; } + public object Prop3 { get; set; } + public object Prop4 { get; set; } + } + + public class PropertyItemTypeNameHandlingDictionary + { + [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)] + public IDictionary Data { get; set; } + } + + public class PropertyItemTypeNameHandling + { + [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)] + public IList Data { get; set; } + } + [JsonArray(ItemTypeNameHandling = TypeNameHandling.All)] public class TypeNameList : List { diff --git a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs index c4a66fe2..8c4cc2d7 100644 --- a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs +++ b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs @@ -43,12 +43,15 @@ namespace Newtonsoft.Json internal bool? _isReference; internal int? _order; internal Required? _required; + internal bool? _itemIsReference; + internal ReferenceLoopHandling? _itemReferenceLoopHandling; + internal TypeNameHandling? _itemTypeNameHandling; - ///// - ///// Gets the collection's items converter. - ///// - ///// The collection's items converter. - //public Type ItemConverterType { get; set; } + /// + /// Gets the collection's items converter. + /// + /// The collection's items converter. + public Type ItemConverterType { get; set; } /// /// Gets or sets the null value handling used when serializing this property. @@ -138,6 +141,24 @@ namespace Newtonsoft.Json /// The name of the property. public string PropertyName { get; set; } + public ReferenceLoopHandling ItemReferenceLoopHandling + { + get { return _itemReferenceLoopHandling ?? default(ReferenceLoopHandling); } + set { _itemReferenceLoopHandling = value; } + } + + public TypeNameHandling ItemTypeNameHandling + { + get { return _itemTypeNameHandling ?? default(TypeNameHandling); } + set { _itemTypeNameHandling = value; } + } + + public bool ItemIsReference + { + get { return _itemIsReference ?? default(bool); } + set { _itemIsReference = value; } + } + /// /// Initializes a new instance of the class. /// diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 2b9c8f29..b9c46670 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -90,7 +90,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.4.14902")] +[assembly: AssemblyFileVersion("4.5.4.14905")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 75d482e3..0f48da09 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -961,7 +961,7 @@ namespace Newtonsoft.Json.Serialization bool hasJsonIgnoreAttribute = JsonTypeReflector.GetAttribute(attributeProvider) != null #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - || JsonTypeReflector.GetAttribute(attributeProvider) != null + || JsonTypeReflector.GetAttribute(attributeProvider) != null #endif ; @@ -997,6 +997,14 @@ namespace Newtonsoft.Json.Serialization property.TypeNameHandling = (propertyAttribute != null) ? propertyAttribute._typeNameHandling : null; property.IsReference = (propertyAttribute != null) ? propertyAttribute._isReference : null; + property.ItemIsReference = (propertyAttribute != null) ? propertyAttribute._itemIsReference : null; + property.ItemConverter = + (propertyAttribute != null && propertyAttribute.ItemConverterType != null) + ? JsonConverterAttribute.CreateJsonConverterInstance(propertyAttribute.ItemConverterType) + : null; + property.ItemReferenceLoopHandling = (propertyAttribute != null) ? propertyAttribute._itemReferenceLoopHandling : null; + property.ItemTypeNameHandling = (propertyAttribute != null) ? propertyAttribute._itemTypeNameHandling : null; + allowNonPublicAccess = false; if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic) allowNonPublicAccess = true; diff --git a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs index 3faf1de6..8e66dd85 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs @@ -35,6 +35,8 @@ namespace Newtonsoft.Json.Serialization /// public class JsonProperty { + internal Required? _required; + // use to cache contract during deserialization internal JsonContract PropertyContract { get; set; } @@ -111,8 +113,6 @@ namespace Newtonsoft.Json.Serialization /// The default value. public object DefaultValue { get; set; } - internal Required? _required; - /// /// Gets a value indicating whether this is required. /// @@ -189,5 +189,10 @@ namespace Newtonsoft.Json.Serialization { return PropertyName; } + + public JsonConverter ItemConverter { get; set; } + public bool? ItemIsReference { get; set; } + public TypeNameHandling? ItemTypeNameHandling { get; set; } + public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index c8e02732..249e116e 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -69,7 +69,7 @@ namespace Newtonsoft.Json.Serialization if (reader.TokenType == JsonToken.StartArray) { if (contract.ContractType == JsonContractType.Array) - PopulateList(CollectionUtils.CreateCollectionWrapper(target), reader, null, (JsonArrayContract) contract); + PopulateList(CollectionUtils.CreateCollectionWrapper(target), reader, null, (JsonArrayContract) contract, null); else throw JsonSerializationException.Create(reader, "Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType)); } @@ -86,9 +86,9 @@ namespace Newtonsoft.Json.Serialization } if (contract.ContractType == JsonContractType.Dictionary) - PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(target), reader, (JsonDictionaryContract) contract, id); + PopulateDictionary(CollectionUtils.CreateDictionaryWrapper(target), reader, (JsonDictionaryContract) contract, null, null, id); else if (contract.ContractType == JsonContractType.Object) - PopulateObject(target, reader, (JsonObjectContract) contract, id); + PopulateObject(target, reader, (JsonObjectContract) contract, null, null, id); else throw JsonSerializationException.Create(reader, "Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType)); } @@ -115,7 +115,7 @@ namespace Newtonsoft.Json.Serialization try { - JsonConverter converter = GetConverter(contract, null, null); + JsonConverter converter = GetConverter(contract, null, null, null); if (reader.TokenType == JsonToken.None && !ReadForType(reader, contract, converter != null, false)) { @@ -125,7 +125,7 @@ namespace Newtonsoft.Json.Serialization return null; } - return CreateValueNonProperty(reader, objectType, contract, converter, null); + return CreateValueNonProperty(reader, objectType, contract, converter, null, null); } catch (Exception ex) { @@ -201,7 +201,7 @@ namespace Newtonsoft.Json.Serialization return token; } - private object CreateValueProperty(JsonReader reader, JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, object target, bool gottenCurrentValue, object currentValue) + private object CreateValueProperty(JsonReader reader, JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, object target, bool gottenCurrentValue, object currentValue) { JsonContract contract; JsonConverter converter; @@ -219,7 +219,7 @@ namespace Newtonsoft.Json.Serialization contract = GetContractSafe(currentValue.GetType()); if (contract != property.PropertyContract) - converter = GetConverter(contract, property.MemberConverter, containerContract); + converter = GetConverter(contract, property.MemberConverter, containerContract, containerProperty); else converter = propertyConverter; } @@ -234,18 +234,18 @@ namespace Newtonsoft.Json.Serialization return converter.ReadJson(reader, objectType, currentValue, GetInternalSerializer()); } - return CreateValueInternal(reader, objectType, contract, property, containerContract, currentValue); + return CreateValueInternal(reader, objectType, contract, property, containerContract, containerProperty, currentValue); } - private object CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract, JsonConverter converter, JsonContainerContract containerContract) + private object CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract, JsonConverter converter, JsonContainerContract containerContract, JsonProperty containerProperty) { if (converter != null && converter.CanRead) return converter.ReadJson(reader, objectType, null, GetInternalSerializer()); - return CreateValueInternal(reader, objectType, contract, null, containerContract, null); + return CreateValueInternal(reader, objectType, contract, null, containerContract, containerProperty, null); } - private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, object existingValue) + private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue) { if (contract != null && contract.ContractType == JsonContractType.Linq) return CreateJToken(reader, contract); @@ -257,9 +257,9 @@ 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, containerContract, existingValue); + return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue); case JsonToken.StartArray: - return CreateList(reader, objectType, contract, member, existingValue, null); + return CreateList(reader, objectType, contract, member, containerMember, existingValue, null); case JsonToken.Integer: case JsonToken.Float: case JsonToken.Boolean: @@ -268,7 +268,7 @@ namespace Newtonsoft.Json.Serialization return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.String: // convert empty string to null automatically for nullable types - if (string.IsNullOrEmpty((string)reader.Value) && objectType != typeof(string) && objectType != typeof(object) && contract.IsNullable) + if (string.IsNullOrEmpty((string)reader.Value) && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable) return null; // string that needs to be returned as a byte array should be base 64 decoded @@ -301,7 +301,7 @@ namespace Newtonsoft.Json.Serialization throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } - private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract) + private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract, JsonProperty containerProperty) { JsonConverter converter = null; if (memberConverter != null) @@ -309,6 +309,10 @@ namespace Newtonsoft.Json.Serialization // member attribute converter converter = memberConverter; } + else if (containerProperty != null && containerProperty.ItemConverter != null) + { + converter = containerProperty.ItemConverter; + } else if (containerContract != null && containerContract.ItemConverter != null) { converter = containerContract.ItemConverter; @@ -329,7 +333,7 @@ namespace Newtonsoft.Json.Serialization return converter; } - private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, object existingValue) + private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue) { CheckedRead(reader); @@ -378,6 +382,7 @@ namespace Newtonsoft.Json.Serialization TypeNameHandling resolvedTypeNameHandling = ((member != null) ? member.TypeNameHandling : null) ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null) + ?? ((containerMember != null) ? containerMember.ItemTypeNameHandling : null) ?? Serializer.TypeNameHandling; if (resolvedTypeNameHandling != TypeNameHandling.None) @@ -399,7 +404,11 @@ namespace Newtonsoft.Json.Serialization if (specifiedType == null) throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName)); - if (objectType != null && !objectType.IsAssignableFrom(specifiedType)) + if (objectType != null +#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) + && objectType != typeof(IDynamicMetaObjectProvider) +#endif + && !objectType.IsAssignableFrom(specifiedType)) throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName)); objectType = specifiedType; @@ -422,7 +431,7 @@ namespace Newtonsoft.Json.Serialization else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal)) { CheckedRead(reader); - object list = CreateList(reader, objectType, contract, member, existingValue, id); + object list = CreateList(reader, objectType, contract, member, containerMember, existingValue, id); CheckedRead(reader); return list; } @@ -446,16 +455,16 @@ namespace Newtonsoft.Json.Serialization case JsonContractType.Object: JsonObjectContract objectContract = (JsonObjectContract) contract; if (existingValue == null) - return CreateAndPopulateObject(reader, objectContract, id); + return CreateAndPopulateObject(reader, objectContract, member, containerMember, id); - return PopulateObject(existingValue, reader, objectContract, id); + return PopulateObject(existingValue, reader, objectContract, member, containerMember, id); case JsonContractType.Primitive: JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract) contract; // if the content is inside $value then read past it if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal)) { CheckedRead(reader); - object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, existingValue); + object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, null, existingValue); CheckedRead(reader); return value; @@ -464,13 +473,13 @@ namespace Newtonsoft.Json.Serialization case JsonContractType.Dictionary: JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) contract; if (existingValue == null) - return CreateAndPopulateDictionary(reader, dictionaryContract, id); + return CreateAndPopulateDictionary(reader, dictionaryContract, member, containerMember, id); - return PopulateDictionary(dictionaryContract.CreateWrapper(existingValue), reader, dictionaryContract, id); + return PopulateDictionary(dictionaryContract.CreateWrapper(existingValue), reader, dictionaryContract, member, containerMember, id); #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) case JsonContractType.Dynamic: JsonDynamicContract dynamicContract = (JsonDynamicContract) contract; - return CreateDynamic(reader, dynamicContract, id); + return CreateDynamic(reader, dynamicContract, member, id); #endif #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) case JsonContractType.Serializable: @@ -504,7 +513,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } - private object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string reference) + private object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonProperty containerProperty, object existingValue, string reference) { object value; if (HasDefinedType(objectType)) @@ -512,9 +521,9 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For JsonArrayContract arrayContract = EnsureArrayContract(reader, objectType, contract); if (existingValue == null) - value = CreateAndPopulateList(reader, reference, arrayContract); + value = CreateAndPopulateList(reader, reference, arrayContract, member, containerProperty); else - value = PopulateList(arrayContract.CreateWrapper(existingValue), reader, reference, arrayContract); + value = PopulateList(arrayContract.CreateWrapper(existingValue), reader, reference, arrayContract, member); } else { @@ -583,7 +592,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For return value.ToString(); } - private void SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonReader reader, object target) + private void SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target) { if (property.Ignored) { @@ -634,7 +643,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, containerContract, target, gottenCurrentValue, existingValue); + object value = CreateValueProperty(reader, property, propertyConverter, containerContract, containerProperty, 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 @@ -669,7 +678,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For return true; } - private object CreateAndPopulateDictionary(JsonReader reader, JsonDictionaryContract contract, string id) + private object CreateAndPopulateDictionary(JsonReader reader, JsonDictionaryContract contract, JsonProperty member, JsonProperty containerProperty, string id) { object dictionary; @@ -681,12 +690,12 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For IWrappedDictionary dictionaryWrapper = contract.CreateWrapper(dictionary); - PopulateDictionary(dictionaryWrapper, reader, contract, id); + PopulateDictionary(dictionaryWrapper, reader, contract, member, containerProperty, id); return dictionaryWrapper.UnderlyingDictionary; } - private object PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, string id) + private object PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty member, JsonProperty containerProperty, string id) { if (id != null) Serializer.ReferenceResolver.AddReference(this, id, dictionary.UnderlyingDictionary); @@ -718,12 +727,12 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For if (contract.ItemContract == null) contract.ItemContract = GetContractSafe(contract.DictionaryValueType); - JsonConverter dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract); + JsonConverter dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); if (!ReadForType(reader, contract.ItemContract, dictionaryValueConverter != null, false)) throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); - dictionary[keyValue] = CreateValueNonProperty(reader, contract.DictionaryValueType, contract.ItemContract, dictionaryValueConverter, contract); + dictionary[keyValue] = CreateValueNonProperty(reader, contract.DictionaryValueType, contract.ItemContract, dictionaryValueConverter, contract, member); } catch (Exception ex) { @@ -747,7 +756,7 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } - private object CreateAndPopulateList(JsonReader reader, string reference, JsonArrayContract contract) + private object CreateAndPopulateList(JsonReader reader, string reference, JsonArrayContract contract, JsonProperty member, JsonProperty containerProperty) { return CollectionUtils.CreateAndPopulateList(contract.CreatedType, (l, isTemporaryListReference) => { @@ -761,11 +770,11 @@ To force JSON arrays to deserialize add the JsonArrayAttribute to the type.".For if (contract.OnError != null && isTemporaryListReference) throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - PopulateList(contract.CreateWrapper(l), reader, reference, contract); + PopulateList(contract.CreateWrapper(l), reader, reference, contract, member); }); } - private object PopulateList(IWrappedCollection wrappedList, JsonReader reader, string reference, JsonArrayContract contract) + private object PopulateList(IWrappedCollection wrappedList, JsonReader reader, string reference, JsonArrayContract contract, JsonProperty containerProperty) { object list = wrappedList.UnderlyingCollection; @@ -785,7 +794,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, contract); + JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty); while (true) { @@ -802,7 +811,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, contract); + object value = CreateValueNonProperty(reader, contract.CollectionItemType, collectionItemContract, collectionItemConverter, contract, containerProperty); wrappedList.Add(value); break; @@ -881,7 +890,7 @@ To fix this error either change the environment to be fully trusted, change the #endif #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) - private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, string id) + private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty member, string id) { IDynamicMetaObjectProvider newObject = null; @@ -922,18 +931,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, null); + JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, null, null); - SetPropertyValue(property, propertyConverter, null, reader, newObject); + SetPropertyValue(property, propertyConverter, null, member, reader, newObject); } else { Type t = (JsonReader.IsPrimitiveToken(reader.TokenType)) ? reader.ValueType : typeof (IDynamicMetaObjectProvider); JsonContract dynamicMemberContract = GetContractSafe(t); - JsonConverter dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null); + JsonConverter dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null, member); - object value = CreateValueNonProperty(reader, t, dynamicMemberContract, dynamicMemberConverter, null); + object value = CreateValueNonProperty(reader, t, dynamicMemberContract, dynamicMemberConverter, null, member); newObject.TrySetMember(memberName, value); } @@ -960,7 +969,7 @@ To fix this error either change the environment to be fully trusted, change the } #endif - private object CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, string id) + private object CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, JsonProperty member, JsonProperty containerProperty, string id) { object newObject = null; @@ -970,7 +979,7 @@ To fix this error either change the environment to be fully trusted, change the if (contract.OverrideConstructor != null) { if (contract.OverrideConstructor.GetParameters().Length > 0) - return CreateObjectFromNonDefaultConstructor(reader, contract, contract.OverrideConstructor, id); + return CreateObjectFromNonDefaultConstructor(reader, contract, containerProperty, contract.OverrideConstructor, id); newObject = contract.OverrideConstructor.Invoke(null); } @@ -985,23 +994,23 @@ To fix this error either change the environment to be fully trusted, change the } else if (contract.ParametrizedConstructor != null) { - return CreateObjectFromNonDefaultConstructor(reader, contract, contract.ParametrizedConstructor, id); + return CreateObjectFromNonDefaultConstructor(reader, contract, containerProperty, contract.ParametrizedConstructor, id); } if (newObject == null) throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - PopulateObject(newObject, reader, contract, id); + PopulateObject(newObject, reader, contract, member, containerProperty, id); return newObject; } - private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, ConstructorInfo constructorInfo, string id) + private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, string id) { ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo"); Type objectType = contract.UnderlyingType; - IDictionary propertyValues = ResolvePropertyAndConstructorValues(contract, reader, objectType); + IDictionary propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, objectType); IDictionary constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object) null); IDictionary remainingPropertyValues = new Dictionary(); @@ -1039,7 +1048,7 @@ To fix this error either change the environment to be fully trusted, change the if (propertyContract.ContractType == JsonContractType.Array) { - JsonArrayContract propertyArrayContract = propertyContract as JsonArrayContract; + JsonArrayContract propertyArrayContract = (JsonArrayContract)propertyContract; object createdObjectCollection = property.ValueProvider.GetValue(createdObject); if (createdObjectCollection != null) @@ -1055,7 +1064,7 @@ To fix this error either change the environment to be fully trusted, change the } else if (propertyContract.ContractType == JsonContractType.Dictionary) { - JsonDictionaryContract jsonDictionaryContract = propertyContract as JsonDictionaryContract; + JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)propertyContract; object createdObjectDictionary = property.ValueProvider.GetValue(createdObject); if (createdObjectDictionary != null) @@ -1076,7 +1085,7 @@ To fix this error either change the environment to be fully trusted, change the return createdObject; } - private IDictionary ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonReader reader, Type objectType) + private IDictionary ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType) { IDictionary propertyValues = new Dictionary(); bool exit = false; @@ -1097,13 +1106,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, contract); + JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, containerProperty); 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, contract, null, true, null); + propertyValues[property] = CreateValueProperty(reader, property, propertyConverter, contract, containerProperty, null, true, null); else reader.Skip(); } @@ -1177,7 +1186,7 @@ To fix this error either change the environment to be fully trusted, change the return (reader.TokenType != JsonToken.None); } - private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, string id) + private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, JsonProperty containerProperty, string id) { contract.InvokeOnDeserializing(newObject, Serializer.Context); @@ -1215,14 +1224,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, contract); + JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, member); 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, contract, reader, newObject); + SetPropertyValue(property, propertyConverter, contract, member, reader, newObject); } catch (Exception ex) { diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 291ccdaa..81efa83f 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -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, JsonContainerContract collectionContract) + private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { if (contract.UnderlyingType == typeof (byte[])) { - bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract); + bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty); if (includeTypeDetails) { writer.WriteStartObject(); @@ -96,7 +96,7 @@ namespace Newtonsoft.Json.Serialization writer.WriteValue(value); } - private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract collectionContract) + private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { if (value == null) { @@ -106,43 +106,44 @@ namespace Newtonsoft.Json.Serialization JsonConverter converter; if ((((converter = (member != null) ? member.Converter : null) != null) - || ((converter = (collectionContract != null) ? collectionContract.ItemConverter : null) != null) + || ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null) + || ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null) || ((converter = valueContract.Converter) != null) || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null) || ((converter = valueContract.InternalConverter) != null)) && converter.CanWrite) { - SerializeConvertable(writer, converter, value, valueContract, collectionContract); + SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty); return; } switch (valueContract.ContractType) { case JsonContractType.Object: - SerializeObject(writer, value, (JsonObjectContract) valueContract, member, collectionContract); + SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Array: JsonArrayContract arrayContract = (JsonArrayContract) valueContract; - SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, collectionContract); + SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, containerContract, containerProperty); break; case JsonContractType.Primitive: - SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, collectionContract); + SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.String: - SerializeString(writer, value, (JsonStringContract) valueContract); + SerializeString(writer, value, (JsonStringContract)valueContract); break; case JsonContractType.Dictionary: JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract; - SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionContract); + SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty); break; #if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE) case JsonContractType.Dynamic: - SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, collectionContract); + SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty); break; #endif #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) case JsonContractType.Serializable: - SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, collectionContract); + SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty); break; #endif case JsonContractType.Linq: @@ -151,7 +152,7 @@ namespace Newtonsoft.Json.Serialization } } - private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract) + private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty) { bool? isReference = null; @@ -159,6 +160,9 @@ namespace Newtonsoft.Json.Serialization if (property != null) isReference = property.IsReference; + if (isReference == null && containerProperty != null) + isReference = containerProperty.ItemIsReference; + if (isReference == null && collectionContract != null) isReference = collectionContract.ItemIsReference; @@ -168,14 +172,14 @@ namespace Newtonsoft.Json.Serialization return isReference; } - private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract) + private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract, JsonProperty containerProperty) { if (value == null) return false; if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String) return false; - bool? isReference = ResolveIsReference(valueContract, property, collectionContract); + bool? isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty); if (isReference == null) { @@ -191,31 +195,6 @@ namespace Newtonsoft.Json.Serialization return Serializer.ReferenceResolver.IsReferenced(this, value); } - private void WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract, JsonObjectContract collectionContract) - { - string propertyName = property.PropertyName; - - if (ShouldWriteReference(memberValue, property, contract, collectionContract)) - { - writer.WritePropertyName(propertyName); - WriteReference(writer, memberValue); - return; - } - - if (!CheckForCircularReference(memberValue, property, contract, collectionContract)) - return; - - if (memberValue == null) - { - Required resolvedRequired = property._required ?? collectionContract.ItemRequired ?? Required.Default; - if (resolvedRequired == 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, collectionContract); - } - private bool ShouldWriteProperty(object memberValue, JsonProperty property) { if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && @@ -229,7 +208,7 @@ namespace Newtonsoft.Json.Serialization return true; } - private bool CheckForCircularReference(object value, JsonProperty property, JsonContract contract, JsonContainerContract collectionContract) + private bool CheckForCircularReference(object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty) { if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) return true; @@ -239,8 +218,11 @@ namespace Newtonsoft.Json.Serialization if (property != null) referenceLoopHandling = property.ReferenceLoopHandling; - if (referenceLoopHandling == null && collectionContract != null) - referenceLoopHandling = collectionContract.ItemReferenceLoopHandling; + if (referenceLoopHandling == null && containerProperty != null) + referenceLoopHandling = containerProperty.ItemReferenceLoopHandling; + + if (referenceLoopHandling == null && containerContract != null) + referenceLoopHandling = containerContract.ItemReferenceLoopHandling; if (_serializeStack.IndexOf(value) != -1) { @@ -321,13 +303,13 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnSerialized(value, Serializer.Context); } - private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract) + private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); - WriteObjectStart(writer, value, contract, member, collectionContract); + WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int initialDepth = writer.Top; @@ -345,7 +327,27 @@ namespace Newtonsoft.Json.Serialization if (ShouldWriteProperty(memberValue, property)) { - WriteMemberInfoProperty(writer, memberValue, property, memberContract, contract); + string propertyName = property.PropertyName; + + if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) + { + writer.WritePropertyName(propertyName); + WriteReference(writer, memberValue); + continue; + } + + if (!CheckForCircularReference(memberValue, property, memberContract, contract, member)) + continue; + + if (memberValue == null) + { + Required resolvedRequired = property._required ?? contract.ItemRequired ?? Required.Default; + if (resolvedRequired == 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, memberContract, property, contract, member); } } } @@ -365,17 +367,17 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnSerialized(value, Serializer.Context); } - private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract) + private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { writer.WriteStartObject(); - bool isReference = ResolveIsReference(contract, member, collectionContract) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects); + bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects); if (isReference) { writer.WritePropertyName(JsonTypeReflector.IdPropertyName); writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value)); } - if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract)) + if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty)) { WriteTypeProperty(writer, contract.UnderlyingType); } @@ -402,15 +404,15 @@ namespace Newtonsoft.Json.Serialization return ((value & flag) == flag); } - private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract) + private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty) { - if (ShouldWriteReference(value, null, contract, collectionContract)) + if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty)) { WriteReference(writer, value); } else { - if (!CheckForCircularReference(value, null, contract, collectionContract)) + if (!CheckForCircularReference(value, null, contract, collectionContract, containerProperty)) return; _serializeStack.Add(value); @@ -421,13 +423,13 @@ namespace Newtonsoft.Json.Serialization } } - private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract) + private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(values.UnderlyingCollection, Serializer.Context); _serializeStack.Add(values.UnderlyingCollection); - bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract); + bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty); writer.WriteStartArray(); @@ -441,15 +443,15 @@ namespace Newtonsoft.Json.Serialization { JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); - if (ShouldWriteReference(value, null, valueContract, contract)) + if (ShouldWriteReference(value, null, valueContract, contract, member)) { WriteReference(writer, value); } else { - if (CheckForCircularReference(value, null, valueContract, contract)) + if (CheckForCircularReference(value, null, valueContract, contract, member)) { - SerializeValue(writer, value, valueContract, null, contract); + SerializeValue(writer, value, valueContract, null, contract, member); } } } @@ -476,10 +478,10 @@ namespace Newtonsoft.Json.Serialization contract.InvokeOnSerialized(values.UnderlyingCollection, Serializer.Context); } - private bool WriteStartArray(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract) + private bool WriteStartArray(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { - bool isReference = ResolveIsReference(contract, member, collectionContract) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays); - bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionContract); + bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays); + bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty); bool writeMetadataObject = isReference || includeTypeDetails; if (writeMetadataObject) @@ -509,7 +511,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, JsonContainerContract collectionContract) + private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { if (!JsonTypeReflector.FullyTrusted) { @@ -520,7 +522,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, collectionContract); + WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter()); value.GetObjectData(serializationInfo, Serializer.Context); @@ -528,7 +530,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, member); } writer.WriteEndObject(); @@ -539,12 +541,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, JsonContainerContract collectionContract) + private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(value, Serializer.Context); _serializeStack.Add(value); - WriteObjectStart(writer, value, contract, member, collectionContract); + WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); foreach (string memberName in value.GetDynamicMemberNames()) { @@ -556,7 +558,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, member); } } @@ -567,43 +569,42 @@ To fix this error either change the environment to be fully trusted, change the } #endif - private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract) + private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) { - TypeNameHandling resolvedTypeNameHandling = ((member != null) ? member.TypeNameHandling : null) - ?? ((collectionContract != null) ? collectionContract.ItemTypeNameHandling : null) + TypeNameHandling resolvedTypeNameHandling = + ((member != null) ? member.TypeNameHandling : null) + ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null) + ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null) ?? Serializer.TypeNameHandling; if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag)) return true; - if (member != null) + // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default) + if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto)) { - if ((member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto - // instance and property type are different - && contract.UnderlyingType != member.PropertyType) + if (member != null) { - JsonContract memberTypeContract = Serializer.ContractResolver.ResolveContract(member.PropertyType); - // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default) - if (contract.UnderlyingType != memberTypeContract.CreatedType) + if (contract.UnderlyingType != member.PropertyContract.CreatedType) + return true; + } + else if (containerContract != null && containerContract.ItemContract != null) + { + if (contract.UnderlyingType != containerContract.ItemContract.CreatedType) return true; } - } - else if (collectionContract != null && collectionContract.ItemContract != null) - { - if (Serializer.TypeNameHandling == TypeNameHandling.Auto && contract.UnderlyingType != collectionContract.ItemContract.CreatedType) - return true; } return false; } - private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract) + private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) { contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context); _serializeStack.Add(values.UnderlyingDictionary); - WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionContract); + WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionContract, containerProperty); if (contract.ItemContract == null) contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object)); @@ -626,19 +627,19 @@ To fix this error either change the environment to be fully trusted, change the object value = entry.Value; JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); - if (ShouldWriteReference(value, null, valueContract, contract)) + if (ShouldWriteReference(value, null, valueContract, contract, member)) { writer.WritePropertyName(propertyName); WriteReference(writer, value); } else { - if (!CheckForCircularReference(value, null, valueContract, contract)) + if (!CheckForCircularReference(value, null, valueContract, contract, member)) continue; writer.WritePropertyName(propertyName); - SerializeValue(writer, value, valueContract, null, contract); + SerializeValue(writer, value, valueContract, null, contract, member); } } catch (Exception ex)