1 #region License 2 // Copyright (c) 2007 James Newton-King 3 // 4 // Permission is hereby granted, free of charge, to any person 5 // obtaining a copy of this software and associated documentation 6 // files (the "Software"), to deal in the Software without 7 // restriction, including without limitation the rights to use, 8 // copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the 10 // Software is furnished to do so, subject to the following 11 // conditions: 12 // 13 // The above copyright notice and this permission notice shall be 14 // included in all copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 // OTHER DEALINGS IN THE SOFTWARE. 24 #endregion 25 26 using System; 27 using System.Collections.Generic; 28 using Newtonsoft.Json.Converters; 29 #if NETFX_CORE 30 using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 31 using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; 32 using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; 33 #elif DNXCORE50 34 using Xunit; 35 using Test = Xunit.FactAttribute; 36 using Assert = Newtonsoft.Json.Tests.XUnitAssert; 37 #else 38 using NUnit.Framework; 39 40 #endif 41 42 namespace Newtonsoft.Json.Tests.Converters 43 { 44 [TestFixture] 45 public class CustomCreationConverterTests : TestFixtureBase 46 { 47 public interface IPerson 48 { 49 string FirstName { get; set; } 50 string LastName { get; set; } 51 DateTime BirthDate { get; set; } 52 } 53 54 public class Employee : IPerson 55 { 56 public string FirstName { get; set; } 57 public string LastName { get; set; } 58 public DateTime BirthDate { get; set; } 59 60 public string Department { get; set; } 61 public string JobTitle { get; set; } 62 } 63 64 public class PersonConverter : CustomCreationConverter<IPerson> 65 { Create(Type objectType)66 public override IPerson Create(Type objectType) 67 { 68 return new Employee(); 69 } 70 } 71 DeserializeObject()72 public void DeserializeObject() 73 { 74 string json = JsonConvert.SerializeObject(new List<Employee> 75 { 76 new Employee 77 { 78 BirthDate = new DateTime(1977, 12, 30, 1, 1, 1, DateTimeKind.Utc), 79 FirstName = "Maurice", 80 LastName = "Moss", 81 Department = "IT", 82 JobTitle = "Support" 83 }, 84 new Employee 85 { 86 BirthDate = new DateTime(1978, 3, 15, 1, 1, 1, DateTimeKind.Utc), 87 FirstName = "Jen", 88 LastName = "Barber", 89 Department = "IT", 90 JobTitle = "Manager" 91 } 92 }, Formatting.Indented); 93 94 //[ 95 // { 96 // "FirstName": "Maurice", 97 // "LastName": "Moss", 98 // "BirthDate": "\/Date(252291661000)\/", 99 // "Department": "IT", 100 // "JobTitle": "Support" 101 // }, 102 // { 103 // "FirstName": "Jen", 104 // "LastName": "Barber", 105 // "BirthDate": "\/Date(258771661000)\/", 106 // "Department": "IT", 107 // "JobTitle": "Manager" 108 // } 109 //] 110 111 List<IPerson> people = JsonConvert.DeserializeObject<List<IPerson>>(json, new PersonConverter()); 112 113 IPerson person = people[0]; 114 115 Assert.AreEqual("Newtonsoft.Json.Tests.Employee", person.GetType().Name); 116 117 Assert.AreEqual("Maurice", person.FirstName); 118 119 Employee employee = (Employee)person; 120 121 Assert.AreEqual("Support", employee.JobTitle); 122 } 123 124 public class MyClass 125 { 126 public string Value { get; set; } 127 128 [JsonConverter(typeof(MyThingConverter))] 129 public IThing Thing { get; set; } 130 } 131 132 public interface IThing 133 { 134 int Number { get; } 135 } 136 137 public class MyThing : IThing 138 { 139 public int Number { get; set; } 140 } 141 142 public class MyThingConverter : CustomCreationConverter<IThing> 143 { Create(Type objectType)144 public override IThing Create(Type objectType) 145 { 146 return new MyThing(); 147 } 148 } 149 150 [Test] AssertDoesDeserialize()151 public void AssertDoesDeserialize() 152 { 153 const string json = @"{ 154 ""Value"": ""A value"", 155 ""Thing"": { 156 ""Number"": 123 157 } 158 } 159 "; 160 MyClass myClass = JsonConvert.DeserializeObject<MyClass>(json); 161 Assert.IsNotNull(myClass); 162 Assert.AreEqual("A value", myClass.Value); 163 Assert.IsNotNull(myClass.Thing); 164 Assert.AreEqual(123, myClass.Thing.Number); 165 } 166 167 [Test] AssertShouldSerializeTest()168 public void AssertShouldSerializeTest() 169 { 170 MyClass myClass = new MyClass 171 { 172 Value = "Foo", 173 Thing = new MyThing { Number = 456, } 174 }; 175 string json = JsonConvert.SerializeObject(myClass); // <-- Exception here 176 177 const string expected = @"{""Value"":""Foo"",""Thing"":{""Number"":456}}"; 178 Assert.AreEqual(expected, json); 179 } 180 181 internal interface IRange<T> 182 { 183 T First { get; } 184 T Last { get; } 185 } 186 187 internal class Range<T> : IRange<T> 188 { 189 public T First { get; set; } 190 public T Last { get; set; } 191 } 192 193 internal class NullInterfaceTestClass 194 { 195 public virtual Guid Id { get; set; } 196 public virtual int? Year { get; set; } 197 public virtual string Company { get; set; } 198 public virtual IRange<decimal> DecimalRange { get; set; } 199 public virtual IRange<int> IntRange { get; set; } 200 public virtual IRange<decimal> NullDecimalRange { get; set; } 201 } 202 203 internal class DecimalRangeConverter : CustomCreationConverter<IRange<decimal>> 204 { Create(Type objectType)205 public override IRange<decimal> Create(Type objectType) 206 { 207 return new Range<decimal>(); 208 } 209 } 210 211 internal class IntRangeConverter : CustomCreationConverter<IRange<int>> 212 { Create(Type objectType)213 public override IRange<int> Create(Type objectType) 214 { 215 return new Range<int>(); 216 } 217 } 218 219 [Test] DeserializeAndConvertNullValue()220 public void DeserializeAndConvertNullValue() 221 { 222 NullInterfaceTestClass initial = new NullInterfaceTestClass 223 { 224 Company = "Company!", 225 DecimalRange = new Range<decimal> { First = 0, Last = 1 }, 226 Id = new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), 227 IntRange = new Range<int> { First = int.MinValue, Last = int.MaxValue }, 228 Year = 2010, 229 NullDecimalRange = null 230 }; 231 232 string json = JsonConvert.SerializeObject(initial, Formatting.Indented); 233 234 StringAssert.AreEqual(@"{ 235 ""Id"": ""00000001-0002-0003-0405-060708090a0b"", 236 ""Year"": 2010, 237 ""Company"": ""Company!"", 238 ""DecimalRange"": { 239 ""First"": 0.0, 240 ""Last"": 1.0 241 }, 242 ""IntRange"": { 243 ""First"": -2147483648, 244 ""Last"": 2147483647 245 }, 246 ""NullDecimalRange"": null 247 }", json); 248 249 NullInterfaceTestClass deserialized = JsonConvert.DeserializeObject<NullInterfaceTestClass>( 250 json, new IntRangeConverter(), new DecimalRangeConverter()); 251 252 Assert.AreEqual("Company!", deserialized.Company); 253 Assert.AreEqual(new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), deserialized.Id); 254 Assert.AreEqual(0, deserialized.DecimalRange.First); 255 Assert.AreEqual(1, deserialized.DecimalRange.Last); 256 Assert.AreEqual(int.MinValue, deserialized.IntRange.First); 257 Assert.AreEqual(int.MaxValue, deserialized.IntRange.Last); 258 Assert.AreEqual(null, deserialized.NullDecimalRange); 259 Assert.AreEqual(2010, deserialized.Year); 260 } 261 } 262 }