2
// Copyright (c) 2007 James Newton-King
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
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
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.
26
#if !(NET35 || NET20 || PORTABLE)
28
using System.Collections.Generic;
29
using System.ComponentModel;
33
using System.Runtime.Serialization;
35
using Newtonsoft.Json.Converters;
36
using Newtonsoft.Json.Linq;
38
using NUnit.Framework;
40
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
41
using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
42
using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
44
using Newtonsoft.Json.Serialization;
45
using Newtonsoft.Json.Tests.TestObjects;
46
using Newtonsoft.Json.Utilities;
47
using System.Globalization;
48
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
50
namespace Newtonsoft.Json.Tests.Documentation
52
public class SerializationTests
54
public void SerializeObject()
56
#region SerializeObject
57
Product product = new Product();
59
product.Name = "Apple";
60
product.ExpiryDate = new DateTime(2008, 12, 28);
61
product.Price = 3.99M;
62
product.Sizes = new string[] { "Small", "Medium", "Large" };
64
string output = JsonConvert.SerializeObject(product);
67
// "ExpiryDate": "2008-12-28T00:00:00",
76
Product deserializedProduct = JsonConvert.DeserializeObject<Product>(output);
80
public void JsonSerializerToStream()
82
#region JsonSerializerToStream
83
Product product = new Product();
84
product.ExpiryDate = new DateTime(2008, 12, 28);
86
JsonSerializer serializer = new JsonSerializer();
87
serializer.Converters.Add(new JavaScriptDateTimeConverter());
88
serializer.NullValueHandling = NullValueHandling.Ignore;
90
using (StreamWriter sw = new StreamWriter(@"c:\json.txt"))
91
using (JsonWriter writer = new JsonTextWriter(sw))
93
serializer.Serialize(writer, product);
94
// {"ExpiryDate":new Date(1230375600000),"Price":0}
99
#region SerializationAttributes
100
[JsonObject(MemberSerialization.OptIn)]
105
public string Name { get; set; }
107
// "2000-12-15T22:11:03"
109
public DateTime BirthDate { get; set; }
111
// new Date(976918263055)
113
[JsonConverter(typeof(JavaScriptDateTimeConverter))]
114
public DateTime LastModified { get; set; }
116
// not serialized because mode is opt-in
117
public string Department { get; set; }
121
#region SerializationCallbacksObject
122
public class SerializationEventTestObject
125
// This member is serialized and deserialized with no change.
126
public int Member1 { get; set; }
128
// The value of this field is set and reset during and
129
// after serialization.
130
public string Member2 { get; set; }
132
// This field is not serialized. The OnDeserializedAttribute
133
// is used to set the member value after serialization.
135
public string Member3 { get; set; }
137
// This field is set to null, but populated after deserialization.
138
public string Member4 { get; set; }
140
public SerializationEventTestObject()
143
Member2 = "Hello World!";
144
Member3 = "This is a nonserialized value";
149
internal void OnSerializingMethod(StreamingContext context)
151
Member2 = "This value went into the data file during serialization.";
155
internal void OnSerializedMethod(StreamingContext context)
157
Member2 = "This value was reset after serialization.";
161
internal void OnDeserializingMethod(StreamingContext context)
163
Member3 = "This value was set during deserialization";
167
internal void OnDeserializedMethod(StreamingContext context)
169
Member4 = "This value was set after deserialization.";
174
public void SerializationCallbacksExample()
176
#region SerializationCallbacksExample
177
SerializationEventTestObject obj = new SerializationEventTestObject();
179
Console.WriteLine(obj.Member1);
181
Console.WriteLine(obj.Member2);
183
Console.WriteLine(obj.Member3);
184
// This is a nonserialized value
185
Console.WriteLine(obj.Member4);
188
string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
191
// "Member2": "This value went into the data file during serialization.",
195
Console.WriteLine(obj.Member1);
197
Console.WriteLine(obj.Member2);
198
// This value was reset after serialization.
199
Console.WriteLine(obj.Member3);
200
// This is a nonserialized value
201
Console.WriteLine(obj.Member4);
204
obj = JsonConvert.DeserializeObject<SerializationEventTestObject>(json);
206
Console.WriteLine(obj.Member1);
208
Console.WriteLine(obj.Member2);
209
// This value went into the data file during serialization.
210
Console.WriteLine(obj.Member3);
211
// This value was set during deserialization
212
Console.WriteLine(obj.Member4);
213
// This value was set after deserialization.
217
public void SerializationErrorHandling()
219
#region SerializationErrorHandling
220
List<string> errors = new List<string>();
222
List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(@"[
223
'2009-09-09T00:00:00Z',
224
'I am not a date and will error!',
228
'1977-02-20T00:00:00Z',
230
'2000-12-01T00:00:00Z'
232
new JsonSerializerSettings
234
Error = delegate(object sender, ErrorEventArgs args)
236
errors.Add(args.ErrorContext.Error.Message);
237
args.ErrorContext.Handled = true;
239
Converters = { new IsoDateTimeConverter() }
242
// 2009-09-09T00:00:00Z
243
// 1977-02-20T00:00:00Z
244
// 2000-12-01T00:00:00Z
246
// The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.
247
// Unexpected token parsing date. Expected String, got StartArray.
248
// Cannot convert null value to System.DateTime.
252
public void SerializationErrorHandlingWithParent()
254
#region SerializationErrorHandlingWithParent
255
List<string> errors = new List<string>();
257
JsonSerializer serializer = new JsonSerializer();
258
serializer.Error += delegate(object sender, ErrorEventArgs args)
260
// only log an error once
261
if (args.CurrentObject == args.ErrorContext.OriginalObject)
262
errors.Add(args.ErrorContext.Error.Message);
267
#region SerializationErrorHandlingAttributeObject
268
public class PersonError
270
private List<string> _roles;
272
public string Name { get; set; }
273
public int Age { get; set; }
274
public List<string> Roles
279
throw new Exception("Roles not loaded!");
283
set { _roles = value; }
285
public string Title { get; set; }
288
internal void OnError(StreamingContext context, ErrorContext errorContext)
290
errorContext.Handled = true;
295
public void SerializationErrorHandlingAttributeExample()
297
#region SerializationErrorHandlingAttributeExample
298
PersonError person = new PersonError
300
Name = "George Michael Bluth",
303
Title = "Mister Manager"
306
string json = JsonConvert.SerializeObject(person, Formatting.Indented);
308
Console.WriteLine(json);
310
// "Name": "George Michael Bluth",
312
// "Title": "Mister Manager"
317
public void PreservingObjectReferencesOff()
319
#region PreservingObjectReferencesOff
320
Person p = new Person
322
BirthDate = new DateTime(1980, 12, 23, 0, 0, 0, DateTimeKind.Utc),
323
LastModified = new DateTime(2009, 2, 20, 12, 59, 21, DateTimeKind.Utc),
327
List<Person> people = new List<Person>();
331
string json = JsonConvert.SerializeObject(people, Formatting.Indented);
335
// "BirthDate": "1980-12-23T00:00:00Z",
336
// "LastModified": "2009-02-20T12:59:21Z"
340
// "BirthDate": "1980-12-23T00:00:00Z",
341
// "LastModified": "2009-02-20T12:59:21Z"
347
public void PreservingObjectReferencesOn()
349
List<Person> people = new List<Person>();
351
#region PreservingObjectReferencesOn
352
string json = JsonConvert.SerializeObject(people, Formatting.Indented,
353
new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
359
// "BirthDate": "1983-03-08T00:00Z",
360
// "LastModified": "2012-03-21T05:40Z"
367
List<Person> deserializedPeople = JsonConvert.DeserializeObject<List<Person>>(json,
368
new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
370
Console.WriteLine(deserializedPeople.Count);
373
Person p1 = deserializedPeople[0];
374
Person p2 = deserializedPeople[1];
376
Console.WriteLine(p1.Name);
378
Console.WriteLine(p2.Name);
381
bool equal = Object.ReferenceEquals(p1, p2);
386
#region PreservingObjectReferencesAttribute
387
[JsonObject(IsReference = true)]
388
public class EmployeeReference
390
public string Name { get; set; }
391
public EmployeeReference Manager { get; set; }
395
#region CustomCreationConverterObject
396
public interface IPerson
398
string FirstName { get; set; }
399
string LastName { get; set; }
400
DateTime BirthDate { get; set; }
403
public class Employee : IPerson
405
public string FirstName { get; set; }
406
public string LastName { get; set; }
407
public DateTime BirthDate { get; set; }
409
public string Department { get; set; }
410
public string JobTitle { get; set; }
413
public class PersonConverter : CustomCreationConverter<IPerson>
415
public override IPerson Create(Type objectType)
417
return new Employee();
422
public void CustomCreationConverterExample()
426
#region CustomCreationConverterExample
429
// "FirstName": "Maurice",
430
// "LastName": "Moss",
431
// "BirthDate": "1981-03-08T00:00Z",
432
// "Department": "IT",
433
// "JobTitle": "Support"
436
// "FirstName": "Jen",
437
// "LastName": "Barber",
438
// "BirthDate": "1985-12-10T00:00Z",
439
// "Department": "IT",
440
// "JobTitle": "Manager"
444
List<IPerson> people = JsonConvert.DeserializeObject<List<IPerson>>(json, new PersonConverter());
446
IPerson person = people[0];
448
Console.WriteLine(person.GetType());
449
// Newtonsoft.Json.Tests.Employee
451
Console.WriteLine(person.FirstName);
454
Employee employee = (Employee)person;
456
Console.WriteLine(employee.JobTitle);
461
public void ContractResolver()
463
#region ContractResolver
464
Product product = new Product
466
ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc),
469
Sizes = new[] { "Small", "Medium", "Large" }
473
JsonConvert.SerializeObject(
476
new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
481
// "expiryDate": "2010-12-20T18:01Z",
492
public void SerializingCollectionsSerializing()
494
#region SerializingCollectionsSerializing
495
Product p1 = new Product
499
ExpiryDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc),
501
Product p2 = new Product
505
ExpiryDate = new DateTime(2009, 7, 31, 0, 0, 0, DateTimeKind.Utc),
508
List<Product> products = new List<Product>();
512
string json = JsonConvert.SerializeObject(products, Formatting.Indented);
515
// "Name": "Product 1",
516
// "ExpiryDate": "2000-12-29T00:00Z",
521
// "Name": "Product 2",
522
// "ExpiryDate": "2009-07-31T00:00Z",
530
public void SerializingCollectionsDeserializing()
532
#region SerializingCollectionsDeserializing
536
'ExpiryDate': '2000-12-29T00:00Z',
542
'ExpiryDate': '2009-07-31T00:00Z',
548
List<Product> products = JsonConvert.DeserializeObject<List<Product>>(json);
550
Console.WriteLine(products.Count);
553
Product p1 = products[0];
555
Console.WriteLine(p1.Name);
560
public void SerializingCollectionsDeserializingDictionaries()
562
#region SerializingCollectionsDeserializingDictionaries
563
string json = @"{""key1"":""value1"",""key2"":""value2""}";
565
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
567
Console.WriteLine(values.Count);
570
Console.WriteLine(values["key1"]);
575
#region SerializingDatesInJson
576
public class LogEntry
578
public string Details { get; set; }
579
public DateTime LogDate { get; set; }
582
public void WriteJsonDates()
584
LogEntry entry = new LogEntry
586
LogDate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc),
587
Details = "Application started."
590
// default as of Json.NET 4.5
591
string isoJson = JsonConvert.SerializeObject(entry);
592
// {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}
594
JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
596
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
598
string microsoftJson = JsonConvert.SerializeObject(entry, microsoftDateFormatSettings);
599
// {"Details":"Application started.","LogDate":"\/Date(1234656000000)\/"}
601
string javascriptJson = JsonConvert.SerializeObject(entry, new JavaScriptDateTimeConverter());
602
// {"Details":"Application started.","LogDate":new Date(1234656000000)}
606
#region ReducingSerializedJsonSizeOptOut
610
public string Model { get; set; }
611
public DateTime Year { get; set; }
612
public List<string> Features { get; set; }
616
public DateTime LastModified { get; set; }
620
#region ReducingSerializedJsonSizeOptIn
622
public class Computer
626
public string Name { get; set; }
628
public decimal SalePrice { get; set; }
631
public string Manufacture { get; set; }
632
public int StockCount { get; set; }
633
public decimal WholeSalePrice { get; set; }
634
public DateTime NextShipmentDate { get; set; }
638
#region ReducingSerializedJsonSizeNullValueHandlingObject
641
public string Name { get; set; }
642
public string Description { get; set; }
643
public string Classification { get; set; }
644
public string Studio { get; set; }
645
public DateTime? ReleaseDate { get; set; }
646
public List<string> ReleaseCountries { get; set; }
650
public void ReducingSerializedJsonSizeNullValueHandlingExample()
652
#region ReducingSerializedJsonSizeNullValueHandlingExample
653
Movie movie = new Movie();
654
movie.Name = "Bad Boys III";
655
movie.Description = "It's no Bad Boys";
657
string included = JsonConvert.SerializeObject(movie,
659
new JsonSerializerSettings { });
662
// "Name": "Bad Boys III",
663
// "Description": "It's no Bad Boys",
664
// "Classification": null,
666
// "ReleaseDate": null,
667
// "ReleaseCountries": null
670
string ignored = JsonConvert.SerializeObject(movie,
672
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
675
// "Name": "Bad Boys III",
676
// "Description": "It's no Bad Boys"
681
#region ReducingSerializedJsonSizeDefaultValueHandlingObject
684
public string Company { get; set; }
685
public decimal Amount { get; set; }
687
// false is default value of bool
688
public bool Paid { get; set; }
689
// null is default value of nullable
690
public DateTime? PaidDate { get; set; }
692
// customize default values
694
public int FollowUpDays { get; set; }
696
public string FollowUpEmailAddress { get; set; }
700
public void ReducingSerializedJsonSizeDefaultValueHandlingExample()
702
#region ReducingSerializedJsonSizeDefaultValueHandlingExample
703
Invoice invoice = new Invoice
705
Company = "Acme Ltd.",
709
FollowUpEmailAddress = string.Empty,
713
string included = JsonConvert.SerializeObject(invoice,
715
new JsonSerializerSettings { });
718
// "Company": "Acme Ltd.",
722
// "FollowUpDays": 30,
723
// "FollowUpEmailAddress": ""
726
string ignored = JsonConvert.SerializeObject(invoice,
728
new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
731
// "Company": "Acme Ltd.",
737
#region ReducingSerializedJsonSizeContractResolverObject
738
public class DynamicContractResolver : DefaultContractResolver
740
private readonly char _startingWithChar;
741
public DynamicContractResolver(char startingWithChar)
743
_startingWithChar = startingWithChar;
746
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
748
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
750
// only serializer properties that start with the specified character
752
properties.Where(p => p.PropertyName.StartsWith(_startingWithChar.ToString())).ToList();
760
public string BookName { get; set; }
761
public decimal BookPrice { get; set; }
762
public string AuthorName { get; set; }
763
public int AuthorAge { get; set; }
764
public string AuthorCountry { get; set; }
768
public void ReducingSerializedJsonSizeContractResolverExample()
770
#region ReducingSerializedJsonSizeContractResolverExample
773
BookName = "The Gathering Storm",
775
AuthorName = "Brandon Sanderson",
777
AuthorCountry = "United States of America"
780
string startingWithA = JsonConvert.SerializeObject(book, Formatting.Indented,
781
new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('A') });
784
// "AuthorName": "Brandon Sanderson",
786
// "AuthorCountry": "United States of America"
789
string startingWithB = JsonConvert.SerializeObject(book, Formatting.Indented,
790
new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('B') });
793
// "BookName": "The Gathering Storm",
794
// "BookPrice": 16.19
799
#region SerializingPartialJsonFragmentsObject
800
public class SearchResult
802
public string Title { get; set; }
803
public string Content { get; set; }
804
public string Url { get; set; }
808
public void SerializingPartialJsonFragmentsExample()
810
#region SerializingPartialJsonFragmentsExample
811
string googleSearchText = @"{
815
'GsearchResultClass': 'GwebSearch',
816
'unescapedUrl': 'http://en.wikipedia.org/wiki/Paris_Hilton',
817
'url': 'http://en.wikipedia.org/wiki/Paris_Hilton',
818
'visibleUrl': 'en.wikipedia.org',
819
'cacheUrl': 'http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org',
820
'title': '<b>Paris Hilton</b> - Wikipedia, the free encyclopedia',
821
'titleNoFormatting': 'Paris Hilton - Wikipedia, the free encyclopedia',
822
'content': '[1] In 2006, she released her debut album...'
825
'GsearchResultClass': 'GwebSearch',
826
'unescapedUrl': 'http://www.imdb.com/name/nm0385296/',
827
'url': 'http://www.imdb.com/name/nm0385296/',
828
'visibleUrl': 'www.imdb.com',
829
'cacheUrl': 'http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com',
830
'title': '<b>Paris Hilton</b>',
831
'titleNoFormatting': 'Paris Hilton',
832
'content': 'Self: Zoolander. Socialite <b>Paris Hilton</b>...'
854
'estimatedResultCount': '59600000',
855
'currentPageIndex': 0,
856
'moreResultsUrl': 'http://www.google.com/search?oe=utf8&ie=utf8...'
859
'responseDetails': null,
860
'responseStatus': 200
863
JObject googleSearch = JObject.Parse(googleSearchText);
865
// get JSON result objects into a list
866
IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
868
// serialize JSON results into .NET objects
869
IList<SearchResult> searchResults = new List<SearchResult>();
870
foreach (JToken result in results)
872
SearchResult searchResult = JsonConvert.DeserializeObject<SearchResult>(result.ToString());
873
searchResults.Add(searchResult);
876
// Title = <b>Paris Hilton</b> - Wikipedia, the free encyclopedia
877
// Content = [1] In 2006, she released her debut album...
878
// Url = http://en.wikipedia.org/wiki/Paris_Hilton
880
// Title = <b>Paris Hilton</b>
881
// Content = Self: Zoolander. Socialite <b>Paris Hilton</b>...
882
// Url = http://www.imdb.com/name/nm0385296/
886
public void SerializeMultidimensionalArrayExample()
888
string[,] famousCouples = new string[,]
896
string json = JsonConvert.SerializeObject(famousCouples, Formatting.Indented);
899
// ["Bonnie", "Clyde"],
900
// ["Donald", "Daisy"],
904
string[,] deserialized = JsonConvert.DeserializeObject<string[,]>(json);
906
Console.WriteLine(deserialized[3, 0] + ", " + deserialized[3, 1]);
b'\\ No newline at end of file'