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 }