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 #if !(NET20 || NET35 || NET40 || NETFX_CORE || PORTABLE || PORTABLE40 || DNXCORE50)
28 using System.Buffers;
29 #endif
30 using System.Collections.Generic;
31 using System.IO;
32 using System.Text;
33 using Newtonsoft.Json.Converters;
34 using Newtonsoft.Json.Linq;
35 using Newtonsoft.Json.Schema;
36 using Newtonsoft.Json.Serialization;
37 #if NETFX_CORE
38 using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
39 using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
40 using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
41 #elif DNXCORE50
42 using Xunit;
43 using Test = Xunit.FactAttribute;
44 using Assert = Newtonsoft.Json.Tests.XUnitAssert;
45 #else
46 using NUnit.Framework;
47 
48 #endif
49 
50 namespace Newtonsoft.Json.Tests
51 {
52     [TestFixture]
53     public class DemoTests : TestFixtureBase
54     {
55         public class HtmlColor
56         {
57             public int Red { get; set; }
58             public int Green { get; set; }
59             public int Blue { get; set; }
60         }
61 
62         [Test]
JsonConverter()63         public void JsonConverter()
64         {
65             HtmlColor red = new HtmlColor
66             {
67                 Red = 255,
68                 Green = 0,
69                 Blue = 0
70             };
71 
72             string json = JsonConvert.SerializeObject(red, new JsonSerializerSettings
73             {
74                 Formatting = Formatting.Indented
75             });
76             // {
77             //   "Red": 255,
78             //   "Green": 0,
79             //   "Blue": 0
80             // }
81 
82             json = JsonConvert.SerializeObject(red, new JsonSerializerSettings
83             {
84                 Formatting = Formatting.Indented,
85                 Converters = { new HtmlColorConverter() }
86             });
87             // "#FF0000"
88 
89             HtmlColor r2 = JsonConvert.DeserializeObject<HtmlColor>(json, new JsonSerializerSettings
90             {
91                 Formatting = Formatting.Indented,
92                 Converters = { new HtmlColorConverter() }
93             });
94             Assert.AreEqual(255, r2.Red);
95             Assert.AreEqual(0, r2.Green);
96             Assert.AreEqual(0, r2.Blue);
97 
98             Assert.AreEqual(@"""#FF0000""", json);
99         }
100 
101         public class PersonDemo
102         {
103             public string Name { get; set; }
104             public int Age { get; set; }
105             public string Job { get; set; }
106         }
107 
108         public class Session
109         {
110             public string Name { get; set; }
111             public DateTime Date { get; set; }
112         }
113 
114         public class HtmlColorConverter : JsonConverter
115         {
WriteJson(JsonWriter writer, object value, JsonSerializer serializer)116             public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
117             {
118                 // create hex string from value
119                 HtmlColor color = (HtmlColor)value;
120                 string hexString = color.Red.ToString("X2")
121                                    + color.Green.ToString("X2")
122                                    + color.Blue.ToString("X2");
123 
124                 // write value to json
125                 writer.WriteValue("#" + hexString);
126             }
127 
128             //public override object ReadJson(JsonReader reader, Type objectType,
129             //    object existingValue, JsonSerializer serializer)
130             //{
131             //    throw new NotImplementedException();
132             //}
133 
ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)134             public override object ReadJson(JsonReader reader, Type objectType,
135                 object existingValue, JsonSerializer serializer)
136             {
137                 // get hex string
138                 string hexString = (string)reader.Value;
139                 hexString = hexString.TrimStart('#');
140 
141                 // build html color from hex
142                 return new HtmlColor
143                 {
144                     Red = Convert.ToInt32(hexString.Substring(0, 2), 16),
145                     Green = Convert.ToInt32(hexString.Substring(2, 2), 16),
146                     Blue = Convert.ToInt32(hexString.Substring(4, 2), 16)
147                 };
148             }
149 
CanConvert(Type objectType)150             public override bool CanConvert(Type objectType)
151             {
152                 return objectType == typeof(HtmlColor);
153             }
154         }
155 
156         [Test]
SerializationGuide()157         public void SerializationGuide()
158         {
159             IList<string> roles = new List<string>
160             {
161                 "User",
162                 "Admin"
163             };
164 
165             string roleJson = JsonConvert.SerializeObject(roles, Formatting.Indented);
166             // [
167             //   "User",
168             //   "Admin"
169             // ]
170 
171             IDictionary<DateTime, int> dailyRegistrations = new Dictionary<DateTime, int>
172             {
173                 { new DateTime(2014, 6, 1), 23 },
174                 { new DateTime(2014, 6, 2), 50 }
175             };
176 
177             string regJson = JsonConvert.SerializeObject(dailyRegistrations, Formatting.Indented);
178             // {
179             //   "2014-06-01T00:00:00": 23,
180             //   "2014-06-02T00:00:00": 50
181             // }
182 
183             City c = new City { Name = "Oslo", Population = 650000 };
184 
185             string cityJson = JsonConvert.SerializeObject(c, Formatting.Indented);
186             // {
187             //   "Name": "Oslo",
188             //   "Population": 650000
189             // }
190         }
191 
192         [Test]
SerializationBasics()193         public void SerializationBasics()
194         {
195             IList<string> roles = new List<string>
196             {
197                 "User",
198                 "Admin"
199             };
200 
201             MemoryTraceWriter traceWriter = new MemoryTraceWriter();
202 
203             string j = JsonConvert.SerializeObject(roles, new JsonSerializerSettings
204             {
205                 Formatting = Formatting.Indented,
206                 TraceWriter = traceWriter
207             });
208 
209             string trace = traceWriter.ToString();
210             // Started serializing System.Collections.Generic.List`1[System.String].
211             // Finished serializing System.Collections.Generic.List`1[System.String].
212             // Verbose Serialized JSON:
213             // [
214             //   "User",
215             //   "Admin"
216             // ]
217         }
218 
219         [Test]
SerializationBasics2()220         public void SerializationBasics2()
221         {
222             var s = new Session
223             {
224                 Name = "Serialize All The Things",
225                 Date = new DateTime(2014, 6, 4, 0, 0, 0, DateTimeKind.Utc)
226             };
227 
228             string j = JsonConvert.SerializeObject(s, new JsonSerializerSettings
229             {
230                 Formatting = Formatting.Indented,
231                 Converters = { new JavaScriptDateTimeConverter() }
232             });
233             // {
234             //   "Name": "Serialize All The Things",
235             //   "Date": new Date(1401796800000)
236             // }
237 
238             StringAssert.AreEqual(@"{
239   ""Name"": ""Serialize All The Things"",
240   ""Date"": new Date(
241     1401840000000
242   )
243 }", j);
244         }
245 
246         [Test]
DeserializationBasics1()247         public void DeserializationBasics1()
248         {
249             string j = @"{
250               'Name': 'Serialize All The Things',
251               'Date': new Date(1401796800000)
252             }";
253 
254             var s = JsonConvert.DeserializeObject<Session>(j, new JsonSerializerSettings
255             {
256                 Converters = { new JavaScriptDateTimeConverter() }
257             });
258             // Name = Serialize All The Things
259             // Date = Tuesday, 3 June 2014
260 
261             Assert.AreEqual("Serialize All The Things", s.Name);
262         }
263 
264         [Test]
DeserializationBasics2()265         public void DeserializationBasics2()
266         {
267             Session s = new Session();
268             s.Date = new DateTime(2014, 6, 4);
269 
270             string j = @"{
271               'Name': 'Serialize All The Things'
272             }";
273 
274             JsonConvert.PopulateObject(j, s);
275             // Name = Serialize All The Things
276             // Date = Tuesday, 3 June 2014
277         }
278 
279         public class City
280         {
281             public string Name { get; set; }
282             public int Population { get; set; }
283         }
284 
285         public class Employee
286         {
287             public string Name { get; set; }
288         }
289 
290         public class Manager : Employee
291         {
292             public IList<Employee> Reportees { get; set; }
293         }
294 
295         [Test]
SerializeReferencesByValue()296         public void SerializeReferencesByValue()
297         {
298             Employee arnie = new Employee { Name = "Arnie Admin" };
299             Manager mike = new Manager { Name = "Mike Manager" };
300             Manager susan = new Manager { Name = "Susan Supervisor" };
301 
302             mike.Reportees = new[] { arnie, susan };
303             susan.Reportees = new[] { arnie };
304 
305             string json = JsonConvert.SerializeObject(mike, Formatting.Indented);
306             // {
307             //   "Reportees": [
308             //     {
309             //       "Name": "Arnie Admin"
310             //     },
311             //     {
312             //       "Reportees": [
313             //         {
314             //           "Name": "Arnie Admin"
315             //         }
316             //       ],
317             //       "Name": "Susan Supervisor"
318             //     }
319             //   ],
320             //   "Name": "Mike Manager"
321             // }
322 
323             StringAssert.AreEqual(@"{
324   ""Reportees"": [
325     {
326       ""Name"": ""Arnie Admin""
327     },
328     {
329       ""Reportees"": [
330         {
331           ""Name"": ""Arnie Admin""
332         }
333       ],
334       ""Name"": ""Susan Supervisor""
335     }
336   ],
337   ""Name"": ""Mike Manager""
338 }", json);
339         }
340 
341         [Test]
SerializeReferencesWithMetadata()342         public void SerializeReferencesWithMetadata()
343         {
344             Employee arnie = new Employee { Name = "Arnie Admin" };
345             Manager mike = new Manager { Name = "Mike Manager" };
346             Manager susan = new Manager { Name = "Susan Supervisor" };
347 
348             mike.Reportees = new[] { arnie, susan };
349             susan.Reportees = new[] { arnie };
350 
351             string json = JsonConvert.SerializeObject(mike, new JsonSerializerSettings
352             {
353                 Formatting = Formatting.Indented,
354                 TypeNameHandling = TypeNameHandling.Objects,
355                 PreserveReferencesHandling = PreserveReferencesHandling.Objects
356             });
357             // {
358             //   "$id": "1",
359             //   "$type": "YourNamespace.Manager, YourAssembly",
360             //   "Name": "Mike Manager",
361             //   "Reportees": [
362             //     {
363             //       "$id": "2",
364             //       "$type": "YourNamespace.Employee, YourAssembly",
365             //       "Name": "Arnie Admin"
366             //     },
367             //     {
368             //       "$id": "3",
369             //       "$type": "YourNamespace.Manager, YourAssembly",
370             //       "Name": "Susan Supervisor",
371             //       "Reportees": [
372             //         {
373             //           "$ref": "2"
374             //         }
375             //       ]
376             //     }
377             //   ]
378             // }
379 
380             StringAssert.AreEqual(@"{
381   ""$id"": ""1"",
382   ""$type"": ""Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests"",
383   ""Reportees"": [
384     {
385       ""$id"": ""2"",
386       ""$type"": ""Newtonsoft.Json.Tests.DemoTests+Employee, Newtonsoft.Json.Tests"",
387       ""Name"": ""Arnie Admin""
388     },
389     {
390       ""$id"": ""3"",
391       ""$type"": ""Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests"",
392       ""Reportees"": [
393         {
394           ""$ref"": ""2""
395         }
396       ],
397       ""Name"": ""Susan Supervisor""
398     }
399   ],
400   ""Name"": ""Mike Manager""
401 }", json);
402         }
403 
404         [Test]
RoundtripTypesAndReferences()405         public void RoundtripTypesAndReferences()
406         {
407             string json = @"{
408   '$id': '1',
409   '$type': 'Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests',
410   'Reportees': [
411     {
412       '$id': '2',
413       '$type': 'Newtonsoft.Json.Tests.DemoTests+Employee, Newtonsoft.Json.Tests',
414       'Name': 'Arnie Admin'
415     },
416     {
417       '$id': '3',
418       '$type': 'Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests',
419       'Reportees': [
420         {
421           '$ref': '2'
422         }
423       ],
424       'Name': 'Susan Supervisor'
425     }
426   ],
427   'Name': 'Mike Manager'
428 }";
429 
430             var e = JsonConvert.DeserializeObject<Employee>(json, new JsonSerializerSettings
431             {
432                 TypeNameHandling = TypeNameHandling.Objects,
433                 PreserveReferencesHandling = PreserveReferencesHandling.Objects
434             });
435             // Name = Mike Manager
436             // Reportees = Arnie Admin, Susan Supervisor
437 
438             Manager mike = (Manager)e;
439             Manager susan = (Manager)mike.Reportees[1];
440 
441             Object.ReferenceEquals(mike.Reportees[0], susan.Reportees[0]);
442             // true
443 
444             Assert.IsTrue(ReferenceEquals(mike.Reportees[0], susan.Reportees[0]));
445         }
446 
447         public class House
448         {
449             public string StreetAddress { get; set; }
450             public DateTime BuildDate { get; set; }
451             public int Bedrooms { get; set; }
452             public decimal FloorArea { get; set; }
453         }
454 
455         public class House1
456         {
457             public string StreetAddress { get; set; }
458 
459             [JsonIgnore]
460             public int Bedrooms { get; set; }
461 
462             [JsonIgnore]
463             public decimal FloorArea { get; set; }
464 
465             [JsonIgnore]
466             public DateTime BuildDate { get; set; }
467         }
468 
469         [JsonObject(MemberSerialization.OptIn)]
470         public class House3
471         {
472             [JsonProperty]
473             public string StreetAddress { get; set; }
474 
475             public int Bedrooms { get; set; }
476             public decimal FloorArea { get; set; }
477             public DateTime BuildDate { get; set; }
478         }
479 
480         [JsonObject(MemberSerialization.OptIn)]
481         public class House2
482         {
483             [JsonProperty("address")]
484             public string StreetAddress { get; set; }
485 
486             public int Bedrooms { get; set; }
487             public decimal FloorArea { get; set; }
488             public DateTime BuildDate { get; set; }
489         }
490 
491         [JsonObject(MemberSerialization.OptIn)]
492         public class House4
493         {
494             [JsonProperty("address", Order = 2)]
495             public string StreetAddress { get; set; }
496 
497             public int Bedrooms { get; set; }
498             public decimal FloorArea { get; set; }
499 
500             [JsonProperty("buildDate", Order = 1)]
501             public DateTime BuildDate { get; set; }
502         }
503 
504         [JsonObject(MemberSerialization.OptIn)]
505         public class House5
506         {
507             [JsonProperty("address", Order = 2)]
508             public string StreetAddress { get; set; }
509 
510             public int Bedrooms { get; set; }
511             public decimal FloorArea { get; set; }
512 
513             [JsonProperty("buildDate", Order = 1)]
514             [JsonConverter(typeof(JavaScriptDateTimeConverter))]
515             public DateTime BuildDate { get; set; }
516         }
517 
518         [Test]
SerializeAttributes()519         public void SerializeAttributes()
520         {
521             var house = new House3();
522             house.StreetAddress = "221B Baker Street";
523             house.Bedrooms = 2;
524             house.FloorArea = 100m;
525             house.BuildDate = new DateTime(1890, 1, 1);
526 
527             string json = JsonConvert.SerializeObject(house, Formatting.Indented);
528             // {
529             //   "StreetAddress": "221B Baker Street",
530             //   "Bedrooms": 2,
531             //   "FloorArea": 100.0,
532             //   "BuildDate": "1890-01-01T00:00:00"
533             // }
534 
535             // {
536             //   "StreetAddress": "221B Baker Street"
537             // }
538 
539             // {
540             //   "address": "221B Baker Street"
541             // }
542 
543             // {
544             //   "buildDate": "1890-01-01T00:00:00",
545             //   "address": "221B Baker Street"
546             // }
547 
548             // {
549             //   "buildDate": new Date(-2524568400000),
550             //   "address": "221B Baker Street"
551             // }
552         }
553 
554         [Test]
MergeJson()555         public void MergeJson()
556         {
557             JObject o1 = JObject.Parse(@"{
558               'FirstName': 'John',
559               'LastName': 'Smith',
560               'Enabled': false,
561               'Roles': [ 'User' ]
562             }");
563             JObject o2 = JObject.Parse(@"{
564               'Enabled': true,
565               'Roles': [ 'User', 'Admin' ]
566             }");
567 
568             o1.Merge(o2, new JsonMergeSettings
569             {
570                 // union arrays together to avoid duplicates
571                 MergeArrayHandling = MergeArrayHandling.Union
572             });
573 
574             string json = o1.ToString();
575             // {
576             //   "FirstName": "John",
577             //   "LastName": "Smith",
578             //   "Enabled": true,
579             //   "Roles": [
580             //     "User",
581             //     "Admin"
582             //   ]
583             // }
584 
585             StringAssert.AreEqual(@"{
586   ""FirstName"": ""John"",
587   ""LastName"": ""Smith"",
588   ""Enabled"": true,
589   ""Roles"": [
590     ""User"",
591     ""Admin""
592   ]
593 }", json);
594         }
595 
596 #if !(NET20 || NET35 || NET40 || NETFX_CORE || PORTABLE || PORTABLE40 || DNXCORE50)
597         [Test]
ArrayPooling()598         public void ArrayPooling()
599         {
600             IList<int> value;
601 
602             JsonSerializer serializer = new JsonSerializer();
603             using (JsonTextReader reader = new JsonTextReader(new StringReader(@"[1,2,3,4]")))
604             {
605                 reader.ArrayPool = JsonArrayPool.Instance;
606 
607                 value = serializer.Deserialize<IList<int>>(reader);
608             }
609 
610             Assert.AreEqual(4, value.Count);
611         }
612 #endif
613     }
614 
615 #if !(NET20 || NET35 || NET40 || NETFX_CORE || PORTABLE || PORTABLE40 || DNXCORE50)
616     public class JsonArrayPool : IArrayPool<char>
617     {
618         public static readonly JsonArrayPool Instance = new JsonArrayPool();
619 
Rent(int minimumLength)620         public char[] Rent(int minimumLength)
621         {
622             // use System.Buffers shared pool
623             return ArrayPool<char>.Shared.Rent(minimumLength);
624         }
625 
Return(char[] array)626         public void Return(char[] array)
627         {
628             // use System.Buffers shared pool
629             ArrayPool<char>.Shared.Return(array);
630         }
631     }
632 #endif
633 }