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 }