#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. #endregion using System; #if !(NET20 || NET35 || NET40 || PORTABLE || PORTABLE40 || DNXCORE50) using System.Buffers; #endif using System.Collections.Generic; using System.IO; using System.Text; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; #if !(NET20 || NET35 || NET40) using System.Threading.Tasks; #endif #if DNXCORE50 using Xunit; using Test = Xunit.FactAttribute; using Assert = Newtonsoft.Json.Tests.XUnitAssert; #else using NUnit.Framework; #endif namespace Newtonsoft.Json.Tests { [TestFixture] public class DemoTests : TestFixtureBase { public class HtmlColor { public int Red { get; set; } public int Green { get; set; } public int Blue { get; set; } } [Test] public void JsonConverter() { HtmlColor red = new HtmlColor { Red = 255, Green = 0, Blue = 0 }; string json = JsonConvert.SerializeObject(red, new JsonSerializerSettings { Formatting = Formatting.Indented }); // { // "Red": 255, // "Green": 0, // "Blue": 0 // } json = JsonConvert.SerializeObject(red, new JsonSerializerSettings { Formatting = Formatting.Indented, Converters = { new HtmlColorConverter() } }); // "#FF0000" HtmlColor r2 = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { Formatting = Formatting.Indented, Converters = { new HtmlColorConverter() } }); Assert.AreEqual(255, r2.Red); Assert.AreEqual(0, r2.Green); Assert.AreEqual(0, r2.Blue); Assert.AreEqual(@"""#FF0000""", json); } public class PersonDemo { public string Name { get; set; } public int Age { get; set; } public string Job { get; set; } } public class Session { public string Name { get; set; } public DateTime Date { get; set; } } public class HtmlColorConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // create hex string from value HtmlColor color = (HtmlColor)value; string hexString = color.Red.ToString("X2") + color.Green.ToString("X2") + color.Blue.ToString("X2"); // write value to json writer.WriteValue("#" + hexString); } //public override object ReadJson(JsonReader reader, Type objectType, // object existingValue, JsonSerializer serializer) //{ // throw new NotImplementedException(); //} public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // get hex string string hexString = (string)reader.Value; hexString = hexString.TrimStart('#'); // build html color from hex return new HtmlColor { Red = Convert.ToInt32(hexString.Substring(0, 2), 16), Green = Convert.ToInt32(hexString.Substring(2, 2), 16), Blue = Convert.ToInt32(hexString.Substring(4, 2), 16) }; } public override bool CanConvert(Type objectType) { return objectType == typeof(HtmlColor); } } [Test] public void SerializationGuide() { IList roles = new List { "User", "Admin" }; string roleJson = JsonConvert.SerializeObject(roles, Formatting.Indented); // [ // "User", // "Admin" // ] IDictionary dailyRegistrations = new Dictionary { { new DateTime(2014, 6, 1), 23 }, { new DateTime(2014, 6, 2), 50 } }; string regJson = JsonConvert.SerializeObject(dailyRegistrations, Formatting.Indented); // { // "2014-06-01T00:00:00": 23, // "2014-06-02T00:00:00": 50 // } City c = new City { Name = "Oslo", Population = 650000 }; string cityJson = JsonConvert.SerializeObject(c, Formatting.Indented); // { // "Name": "Oslo", // "Population": 650000 // } } [Test] public void SerializationBasics() { IList roles = new List { "User", "Admin" }; MemoryTraceWriter traceWriter = new MemoryTraceWriter(); string j = JsonConvert.SerializeObject(roles, new JsonSerializerSettings { Formatting = Formatting.Indented, TraceWriter = traceWriter }); string trace = traceWriter.ToString(); // Started serializing System.Collections.Generic.List`1[System.String]. // Finished serializing System.Collections.Generic.List`1[System.String]. // Verbose Serialized JSON: // [ // "User", // "Admin" // ] } [Test] public void SerializationBasics2() { var s = new Session { Name = "Serialize All The Things", Date = new DateTime(2014, 6, 4, 0, 0, 0, DateTimeKind.Utc) }; string j = JsonConvert.SerializeObject(s, new JsonSerializerSettings { Formatting = Formatting.Indented, Converters = { new JavaScriptDateTimeConverter() } }); // { // "Name": "Serialize All The Things", // "Date": new Date(1401796800000) // } StringAssert.AreEqual(@"{ ""Name"": ""Serialize All The Things"", ""Date"": new Date( 1401840000000 ) }", j); } [Test] public void DeserializationBasics1() { string j = @"{ 'Name': 'Serialize All The Things', 'Date': new Date(1401796800000) }"; var s = JsonConvert.DeserializeObject(j, new JsonSerializerSettings { Converters = { new JavaScriptDateTimeConverter() } }); // Name = Serialize All The Things // Date = Tuesday, 3 June 2014 Assert.AreEqual("Serialize All The Things", s.Name); } [Test] public void DeserializationBasics2() { Session s = new Session(); s.Date = new DateTime(2014, 6, 4); string j = @"{ 'Name': 'Serialize All The Things' }"; JsonConvert.PopulateObject(j, s); // Name = Serialize All The Things // Date = Tuesday, 3 June 2014 } public class City { public string Name { get; set; } public int Population { get; set; } } public class Employee { public string Name { get; set; } } public class Manager : Employee { public IList Reportees { get; set; } } [Test] public void SerializeReferencesByValue() { Employee arnie = new Employee { Name = "Arnie Admin" }; Manager mike = new Manager { Name = "Mike Manager" }; Manager susan = new Manager { Name = "Susan Supervisor" }; mike.Reportees = new[] { arnie, susan }; susan.Reportees = new[] { arnie }; string json = JsonConvert.SerializeObject(mike, Formatting.Indented); // { // "Reportees": [ // { // "Name": "Arnie Admin" // }, // { // "Reportees": [ // { // "Name": "Arnie Admin" // } // ], // "Name": "Susan Supervisor" // } // ], // "Name": "Mike Manager" // } StringAssert.AreEqual(@"{ ""Reportees"": [ { ""Name"": ""Arnie Admin"" }, { ""Reportees"": [ { ""Name"": ""Arnie Admin"" } ], ""Name"": ""Susan Supervisor"" } ], ""Name"": ""Mike Manager"" }", json); } [Test] public void SerializeReferencesWithMetadata() { Employee arnie = new Employee { Name = "Arnie Admin" }; Manager mike = new Manager { Name = "Mike Manager" }; Manager susan = new Manager { Name = "Susan Supervisor" }; mike.Reportees = new[] { arnie, susan }; susan.Reportees = new[] { arnie }; string json = JsonConvert.SerializeObject(mike, new JsonSerializerSettings { Formatting = Formatting.Indented, TypeNameHandling = TypeNameHandling.Objects, PreserveReferencesHandling = PreserveReferencesHandling.Objects }); // { // "$id": "1", // "$type": "YourNamespace.Manager, YourAssembly", // "Name": "Mike Manager", // "Reportees": [ // { // "$id": "2", // "$type": "YourNamespace.Employee, YourAssembly", // "Name": "Arnie Admin" // }, // { // "$id": "3", // "$type": "YourNamespace.Manager, YourAssembly", // "Name": "Susan Supervisor", // "Reportees": [ // { // "$ref": "2" // } // ] // } // ] // } StringAssert.AreEqual(@"{ ""$id"": ""1"", ""$type"": ""Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests"", ""Reportees"": [ { ""$id"": ""2"", ""$type"": ""Newtonsoft.Json.Tests.DemoTests+Employee, Newtonsoft.Json.Tests"", ""Name"": ""Arnie Admin"" }, { ""$id"": ""3"", ""$type"": ""Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests"", ""Reportees"": [ { ""$ref"": ""2"" } ], ""Name"": ""Susan Supervisor"" } ], ""Name"": ""Mike Manager"" }", json); } [Test] public void RoundtripTypesAndReferences() { string json = @"{ '$id': '1', '$type': 'Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests', 'Reportees': [ { '$id': '2', '$type': 'Newtonsoft.Json.Tests.DemoTests+Employee, Newtonsoft.Json.Tests', 'Name': 'Arnie Admin' }, { '$id': '3', '$type': 'Newtonsoft.Json.Tests.DemoTests+Manager, Newtonsoft.Json.Tests', 'Reportees': [ { '$ref': '2' } ], 'Name': 'Susan Supervisor' } ], 'Name': 'Mike Manager' }"; var e = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, PreserveReferencesHandling = PreserveReferencesHandling.Objects }); // Name = Mike Manager // Reportees = Arnie Admin, Susan Supervisor Manager mike = (Manager)e; Manager susan = (Manager)mike.Reportees[1]; Object.ReferenceEquals(mike.Reportees[0], susan.Reportees[0]); // true Assert.IsTrue(ReferenceEquals(mike.Reportees[0], susan.Reportees[0])); } public class House { public string StreetAddress { get; set; } public DateTime BuildDate { get; set; } public int Bedrooms { get; set; } public decimal FloorArea { get; set; } } public class House1 { public string StreetAddress { get; set; } [JsonIgnore] public int Bedrooms { get; set; } [JsonIgnore] public decimal FloorArea { get; set; } [JsonIgnore] public DateTime BuildDate { get; set; } } [JsonObject(MemberSerialization.OptIn)] public class House3 { [JsonProperty] public string StreetAddress { get; set; } public int Bedrooms { get; set; } public decimal FloorArea { get; set; } public DateTime BuildDate { get; set; } } [JsonObject(MemberSerialization.OptIn)] public class House2 { [JsonProperty("address")] public string StreetAddress { get; set; } public int Bedrooms { get; set; } public decimal FloorArea { get; set; } public DateTime BuildDate { get; set; } } [JsonObject(MemberSerialization.OptIn)] public class House4 { [JsonProperty("address", Order = 2)] public string StreetAddress { get; set; } public int Bedrooms { get; set; } public decimal FloorArea { get; set; } [JsonProperty("buildDate", Order = 1)] public DateTime BuildDate { get; set; } } [JsonObject(MemberSerialization.OptIn)] public class House5 { [JsonProperty("address", Order = 2)] public string StreetAddress { get; set; } public int Bedrooms { get; set; } public decimal FloorArea { get; set; } [JsonProperty("buildDate", Order = 1)] [JsonConverter(typeof(JavaScriptDateTimeConverter))] public DateTime BuildDate { get; set; } } [Test] public void SerializeAttributes() { var house = new House3(); house.StreetAddress = "221B Baker Street"; house.Bedrooms = 2; house.FloorArea = 100m; house.BuildDate = new DateTime(1890, 1, 1); string json = JsonConvert.SerializeObject(house, Formatting.Indented); // { // "StreetAddress": "221B Baker Street", // "Bedrooms": 2, // "FloorArea": 100.0, // "BuildDate": "1890-01-01T00:00:00" // } // { // "StreetAddress": "221B Baker Street" // } // { // "address": "221B Baker Street" // } // { // "buildDate": "1890-01-01T00:00:00", // "address": "221B Baker Street" // } // { // "buildDate": new Date(-2524568400000), // "address": "221B Baker Street" // } } [Test] public void MergeJson() { JObject o1 = JObject.Parse(@"{ 'FirstName': 'John', 'LastName': 'Smith', 'Enabled': false, 'Roles': [ 'User' ] }"); JObject o2 = JObject.Parse(@"{ 'Enabled': true, 'Roles': [ 'User', 'Admin' ] }"); o1.Merge(o2, new JsonMergeSettings { // union arrays together to avoid duplicates MergeArrayHandling = MergeArrayHandling.Union }); string json = o1.ToString(); // { // "FirstName": "John", // "LastName": "Smith", // "Enabled": true, // "Roles": [ // "User", // "Admin" // ] // } StringAssert.AreEqual(@"{ ""FirstName"": ""John"", ""LastName"": ""Smith"", ""Enabled"": true, ""Roles"": [ ""User"", ""Admin"" ] }", json); } #if !(NET20 || NET35 || NET40 || PORTABLE || PORTABLE40 || DNXCORE50) [Test] public void ArrayPooling() { IList value; JsonSerializer serializer = new JsonSerializer(); using (JsonTextReader reader = new JsonTextReader(new StringReader(@"[1,2,3,4]"))) { reader.ArrayPool = JsonArrayPool.Instance; value = serializer.Deserialize>(reader); } Assert.AreEqual(4, value.Count); } #endif #if !(NET20 || NET35 || NET40 || PORTABLE || PORTABLE40 || DNXCORE50) [Test] public async Task AsyncDemo() { JArray largeJson; // read asynchronously from a file using (TextReader textReader = new StreamReader(new FileStream(ResolvePath(@"large.json"), FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))) { largeJson = await JArray.LoadAsync(new JsonTextReader(textReader)); } JToken user = largeJson.SelectToken("$[?(@.name == 'Woodard Caldwell')]"); user["isActive"] = false; // write asynchronously to a file using (TextWriter textWriter = new StreamWriter(new FileStream(ResolvePath(@"large.json"), FileMode.Open, FileAccess.Write, FileShare.Write, 4096, true))) { await largeJson.WriteToAsync(new JsonTextWriter(textWriter)); } } #endif } #if !(NET20 || NET35 || NET40 || PORTABLE || PORTABLE40 || DNXCORE50) public class JsonArrayPool : IArrayPool { public static readonly JsonArrayPool Instance = new JsonArrayPool(); public char[] Rent(int minimumLength) { // use System.Buffers shared pool return ArrayPool.Shared.Rent(minimumLength); } public void Return(char[] array) { // use System.Buffers shared pool ArrayPool.Shared.Return(array); } } #endif }