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.
27 using System.Collections.Generic;
28 using System.Globalization;
31 using NUnit.Framework;
32 using Newtonsoft.Json.Linq;
35 using Newtonsoft.Json.Converters;
36 using Newtonsoft.Json.Tests.TestObjects;
38 namespace Newtonsoft.Json.Tests.Linq
40 public class LinqToJsonTest : TestFixtureBase
43 public void DoubleValue()
45 JArray j = JArray.Parse("[-1E+4,100.0e-2]");
47 double value = (double)j[0];
48 Assert.AreEqual(-10000d, value);
51 Assert.AreEqual(1d, value);
57 JArray array = new JArray();
58 JValue text = new JValue("Manual text");
59 JValue date = new JValue(new DateTime(2000, 5, 23));
64 string json = array.ToString();
67 // "\/Date(958996800000+1200)\/"
72 public void LinqToJsonDeserialize()
74 JObject o = new JObject(
75 new JProperty("Name", "John Smith"),
76 new JProperty("BirthDate", new DateTime(1983, 3, 20))
79 JsonSerializer serializer = new JsonSerializer();
80 Person p = (Person)serializer.Deserialize(new JTokenReader(o), typeof(Person));
83 Console.WriteLine(p.Name);
87 public void ObjectParse()
93 ""500 gigabyte hard drive""
97 JObject o = JObject.Parse(json);
98 IList<JProperty> properties = o.Properties().ToList();
100 Assert.AreEqual("CPU", properties[0].Name);
101 Assert.AreEqual("Intel", (string)properties[0].Value);
102 Assert.AreEqual("Drives", properties[1].Name);
104 JArray list = (JArray)properties[1].Value;
105 Assert.AreEqual(2, list.Children().Count());
106 Assert.AreEqual("DVD read/writer", (string)list.Children().ElementAt(0));
107 Assert.AreEqual("500 gigabyte hard drive", (string)list.Children().ElementAt(1));
109 List<object> parameterValues =
110 (from p in o.Properties()
111 where p.Value is JValue
112 select ((JValue)p.Value).Value).ToList();
114 Assert.AreEqual(1, parameterValues.Count);
115 Assert.AreEqual("Intel", parameterValues[0]);
119 public void CreateLongArray()
121 string json = @"[0,1,2,3,4,5,6,7,8,9]";
123 JArray a = JArray.Parse(json);
124 List<int> list = a.Values<int>().ToList();
126 List<int> expected = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
128 CollectionAssert.AreEqual(expected, list);
132 public void GoogleSearchAPI()
139 GsearchResultClass:""GwebSearch"",
140 unescapedUrl : ""http://www.google.com/"",
141 url : ""http://www.google.com/"",
142 visibleUrl : ""www.google.com"",
144 ""http://www.google.com/search?q=cache:zhool8dxBV4J:www.google.com"",
146 titleNoFormatting : ""Google"",
147 content : ""Enables users to search the Web, Usenet, and
148 images. Features include PageRank, caching and translation of
149 results, and an option to find similar pages.""
152 GsearchResultClass:""GwebSearch"",
153 unescapedUrl : ""http://news.google.com/"",
154 url : ""http://news.google.com/"",
155 visibleUrl : ""news.google.com"",
157 ""http://www.google.com/search?q=cache:Va_XShOz_twJ:news.google.com"",
158 title : ""Google News"",
159 titleNoFormatting : ""Google News"",
160 content : ""Aggregated headlines and a search engine of many of the world's news sources.""
164 GsearchResultClass:""GwebSearch"",
165 unescapedUrl : ""http://groups.google.com/"",
166 url : ""http://groups.google.com/"",
167 visibleUrl : ""groups.google.com"",
169 ""http://www.google.com/search?q=cache:x2uPD3hfkn0J:groups.google.com"",
170 title : ""Google Groups"",
171 titleNoFormatting : ""Google Groups"",
172 content : ""Enables users to search and browse the Usenet
173 archives which consist of over 700 million messages, and post new
178 GsearchResultClass:""GwebSearch"",
179 unescapedUrl : ""http://maps.google.com/"",
180 url : ""http://maps.google.com/"",
181 visibleUrl : ""maps.google.com"",
183 ""http://www.google.com/search?q=cache:dkf5u2twBXIJ:maps.google.com"",
184 title : ""Google Maps"",
185 titleNoFormatting : ""Google Maps"",
186 content : ""Provides directions, interactive maps, and
187 satellite/aerial imagery of the United States. Can also search by
188 keyword such as type of business.""
195 GsearchResultClass:""GwebSearch.ad"",
196 title : ""Gartner Symposium/ITxpo"",
197 content1 : ""Meet brilliant Gartner IT analysts"",
198 content2 : ""20-23 May 2007- Barcelona, Spain"",
200 ""http://www.google.com/url?sa=L&ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB&num=1&q=http://www.gartner.com/it/sym/2007/spr8/spr8.jsp%3Fsrc%3D_spain_07_%26WT.srch%3D1&usg=__CxRH06E4Xvm9Muq13S4MgMtnziY="",
203 ""http://www.google.com/uds/css/ad-indicator-on.gif?ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB"",
206 ""http://www.google.com/url?sa=L&ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB&num=1&q=http://www.gartner.com/it/sym/2007/spr8/spr8.jsp%3Fsrc%3D_spain_07_%26WT.srch%3D1&usg=__CxRH06E4Xvm9Muq13S4MgMtnziY="",
208 visibleUrl : ""www.gartner.com""
215 JObject o = JObject.Parse(json);
217 List<JObject> resultObjects = o["results"].Children<JObject>().ToList();
219 Assert.AreEqual(32, resultObjects.Properties().Count());
221 Assert.AreEqual(32, resultObjects.Cast<JToken>().Values().Count());
223 Assert.AreEqual(4, resultObjects.Cast<JToken>().Values("GsearchResultClass").Count());
225 Assert.AreEqual(5, o.PropertyValues().Cast<JArray>().Children().Count());
227 List<string> resultUrls = o["results"].Children().Values<string>("url").ToList();
229 List<string> expectedUrls = new List<string>() { "http://www.google.com/", "http://news.google.com/", "http://groups.google.com/", "http://maps.google.com/" };
231 CollectionAssert.AreEqual(expectedUrls, resultUrls);
233 List<JToken> descendants = o.Descendants().ToList();
234 Assert.AreEqual(89, descendants.Count);
238 public void JTokenToString()
244 ""500 gigabyte hard drive""
248 JObject o = JObject.Parse(json);
254 ""500 gigabyte hard drive""
258 JArray list = o.Value<JArray>("Drives");
262 ""500 gigabyte hard drive""
263 ]", list.ToString());
265 JProperty cpuProperty = o.Property("CPU");
266 Assert.AreEqual(@"""CPU"": ""Intel""", cpuProperty.ToString());
268 JProperty drivesProperty = o.Property("Drives");
269 Assert.AreEqual(@"""Drives"": [
271 ""500 gigabyte hard drive""
272 ]", drivesProperty.ToString());
276 public void JTokenToStringTypes()
278 string json = @"{""Color"":2,""Establised"":new Date(1264118400000),""Width"":1.1,""Employees"":999,""RoomsPerFloor"":[1,2,3,4,5,6,7,8,9],""Open"":false,""Symbol"":""@"",""Mottos"":[""Hello World"",""öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~"",null,"" ""],""Cost"":100980.1,""Escape"":""\r\n\t\f\b?{\\r\\n\""'"",""product"":[{""Name"":""Rocket"",""ExpiryDate"":new Date(949532490000),""Price"":0},{""Name"":""Alien"",""ExpiryDate"":new Date(-62135596800000),""Price"":0}]}";
280 JObject o = JObject.Parse(json);
282 Assert.AreEqual(@"""Establised"": new Date(
284 )", o.Property("Establised").ToString());
285 Assert.AreEqual(@"new Date(
287 )", o.Property("Establised").Value.ToString());
288 Assert.AreEqual(@"""Width"": 1.1", o.Property("Width").ToString());
289 Assert.AreEqual(@"1.1", ((JValue)o.Property("Width").Value).ToString(CultureInfo.InvariantCulture));
290 Assert.AreEqual(@"""Open"": false", o.Property("Open").ToString());
291 Assert.AreEqual(@"False", o.Property("Open").Value.ToString());
293 json = @"[null,undefined]";
295 JArray a = JArray.Parse(json);
300 Assert.AreEqual(@"", a.Children().ElementAt(0).ToString());
301 Assert.AreEqual(@"", a.Children().ElementAt(1).ToString());
305 public void CreateJTokenTree()
309 new JProperty("Test1", "Test1Value"),
310 new JProperty("Test2", "Test2Value"),
311 new JProperty("Test3", "Test3Value"),
312 new JProperty("Test4", null)
315 Assert.AreEqual(4, o.Properties().Count());
318 ""Test1"": ""Test1Value"",
319 ""Test2"": ""Test2Value"",
320 ""Test3"": ""Test3Value"",
327 new DateTime(2000, 10, 10, 0, 0, 0, DateTimeKind.Utc),
333 new DateTime(4, 5, 6, 7, 8, 9, DateTimeKind.Utc)
343 Assert.AreEqual(5, a.Count());
346 ""Test1"": ""Test1Value"",
347 ""Test2"": ""Test2Value"",
348 ""Test3"": ""Test3Value"",
351 ""\/Date(971136000000)\/"",
357 ""\/Date(-62030076711000)\/""
369 public string Title { get; set; }
370 public string Description { get; set; }
371 public string Link { get; set; }
372 public IList<string> Categories { get; set; }
375 private List<Post> GetPosts()
377 return new List<Post>()
381 Title = "LINQ to JSON beta",
382 Description = "Annoucing LINQ to JSON",
383 Link = "http://james.newtonking.com/projects/json-net.aspx",
384 Categories = new List<string>() { "Json.NET", "LINQ" }
388 Title = "Json.NET 1.3 + New license + Now on CodePlex",
389 Description = "Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex",
390 Link = "http://james.newtonking.com/projects/json-net.aspx",
391 Categories = new List<string>() { "Json.NET", "CodePlex" }
397 public void CreateJTokenTreeNested()
399 List<Post> posts = GetPosts();
403 new JProperty("channel",
405 new JProperty("title", "James Newton-King"),
406 new JProperty("link", "http://james.newtonking.com"),
407 new JProperty("description", "James Newton-King's blog."),
408 new JProperty("item",
413 new JProperty("title", p.Title),
414 new JProperty("description", p.Description),
415 new JProperty("link", p.Link),
416 new JProperty("category",
418 from c in p.Categories
419 select new JValue(c)))))))));
421 Console.WriteLine(rss.ToString());
425 // "title": "James Newton-King",
426 // "link": "http://james.newtonking.com",
427 // "description": "James Newton-King's blog.",
430 // "title": "Json.NET 1.3 + New license + Now on CodePlex",
431 // "description": "Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex",
432 // "link": "http://james.newtonking.com/projects/json-net.aspx",
439 // "title": "LINQ to JSON beta",
440 // "description": "Annoucing LINQ to JSON",
441 // "link": "http://james.newtonking.com/projects/json-net.aspx",
452 from p in rss["channel"]["item"]
453 select p.Value<string>("title");
455 foreach (var item in postTitles)
457 Console.WriteLine(item);
461 //Json.NET 1.3 + New license + Now on CodePlex
464 from c in rss["channel"]["item"].Children()["category"].Values<string>()
466 orderby g.Count() descending
467 select new { Category = g.Key, Count = g.Count() };
469 foreach (var c in categories)
471 Console.WriteLine(c.Category + " - Count: " + c.Count);
474 //Json.NET - Count: 2
476 //CodePlex - Count: 1
480 public void BasicQuerying()
484 ""title"": ""James Newton-King"",
485 ""link"": ""http://james.newtonking.com"",
486 ""description"": ""James Newton-King's blog."",
489 ""title"": ""Json.NET 1.3 + New license + Now on CodePlex"",
490 ""description"": ""Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex"",
491 ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
498 ""title"": ""LINQ to JSON beta"",
499 ""description"": ""Annoucing LINQ to JSON"",
500 ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
510 JObject o = JObject.Parse(json);
512 Assert.AreEqual(null, o["purple"]);
513 Assert.AreEqual(null, o.Value<string>("purple"));
515 Assert.IsInstanceOfType(typeof(JArray), o["channel"]["item"]);
517 Assert.AreEqual(2, o["channel"]["item"].Children()["title"].Count());
518 Assert.AreEqual(0, o["channel"]["item"].Children()["monkey"].Count());
520 Assert.AreEqual("Json.NET 1.3 + New license + Now on CodePlex", (string)o["channel"]["item"][0]["title"]);
522 CollectionAssert.AreEqual(new string[] { "Json.NET 1.3 + New license + Now on CodePlex", "LINQ to JSON beta" }, o["channel"]["item"].Children().Values<string>("title").ToArray());
526 [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Accessed JObject values with invalid key value: 0. Object property name expected.")]
527 public void JObjectIntIndex()
529 JObject o = new JObject();
530 Assert.AreEqual(null, o[0]);
534 [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"Accessed JArray values with invalid key value: ""purple"". Array position index expected.")]
535 public void JArrayStringIndex()
537 JArray a = new JArray();
538 Assert.AreEqual(null, a["purple"]);
542 [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"Accessed JConstructor values with invalid key value: ""purple"". Argument position index expected.")]
543 public void JConstructorStringIndex()
545 JConstructor c = new JConstructor("ConstructorValue");
546 Assert.AreEqual(null, c["purple"]);
549 #if !PocketPC && !NET20
551 public void ToStringJsonConverter()
555 new JProperty("Test1", new DateTime(2000, 10, 15, 5, 5, 5, DateTimeKind.Utc)),
556 new JProperty("Test2", new DateTimeOffset(2000, 10, 15, 5, 5, 5, new TimeSpan(11, 11, 0))),
557 new JProperty("Test3", "Test3Value"),
558 new JProperty("Test4", null)
561 JsonSerializer serializer = new JsonSerializer();
562 serializer.Converters.Add(new JavaScriptDateTimeConverter());
563 StringWriter sw = new StringWriter();
564 JsonWriter writer = new JsonTextWriter(sw);
565 writer.Formatting = Formatting.Indented;
566 serializer.Serialize(writer, o);
568 string json = sw.ToString();
577 ""Test3"": ""Test3Value"",
583 public void DateTimeOffset()
585 List<DateTimeOffset> testDates = new List<DateTimeOffset> {
586 new DateTimeOffset(new DateTime(100, 1, 1, 1, 1, 1, DateTimeKind.Utc)),
587 new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.Zero),
588 new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(13)),
589 new DateTimeOffset(2000, 1, 1, 1, 1, 1, TimeSpan.FromHours(-3.5)),
592 JsonSerializer jsonSerializer = new JsonSerializer();
594 JTokenWriter jsonWriter;
595 using (jsonWriter = new JTokenWriter())
597 jsonSerializer.Serialize(jsonWriter, testDates);
600 Assert.AreEqual(4, jsonWriter.Token.Children().Count());
605 public void FromObject()
607 List<Post> posts = GetPosts();
609 JObject o = JObject.FromObject(new
613 title = "James Newton-King",
614 link = "http://james.newtonking.com",
615 description = "James Newton-King's blog.",
622 description = p.Description,
624 category = p.Categories
629 Console.WriteLine(o.ToString());
630 Assert.IsInstanceOfType(typeof(JObject), o);
631 Assert.IsInstanceOfType(typeof(JObject), o["channel"]);
632 Assert.AreEqual("James Newton-King", (string)o["channel"]["title"]);
633 Assert.AreEqual(2, o["channel"]["item"].Children().Count());
635 JArray a = JArray.FromObject(new List<int>() { 0, 1, 2, 3, 4 });
636 Assert.IsInstanceOfType(typeof(JArray), a);
637 Assert.AreEqual(5, a.Count());
641 public void FromAnonDictionary()
643 List<Post> posts = GetPosts();
645 JObject o = JObject.FromObject(new
647 channel = new Dictionary<string, object>
649 { "title", "James Newton-King" },
650 { "link", "http://james.newtonking.com" },
651 { "description", "James Newton-King's blog." },
658 description = p.Description,
660 category = p.Categories
666 Console.WriteLine(o.ToString());
667 Assert.IsInstanceOfType(typeof(JObject), o);
668 Assert.IsInstanceOfType(typeof(JObject), o["channel"]);
669 Assert.AreEqual("James Newton-King", (string)o["channel"]["title"]);
670 Assert.AreEqual(2, o["channel"]["item"].Children().Count());
672 JArray a = JArray.FromObject(new List<int>() { 0, 1, 2, 3, 4 });
673 Assert.IsInstanceOfType(typeof(JArray), a);
674 Assert.AreEqual(5, a.Count());
678 public void AsJEnumerable()
681 IJEnumerable<JToken> enumerable = null;
683 enumerable = o.AsJEnumerable();
684 Assert.IsNull(enumerable);
688 new JProperty("Test1", new DateTime(2000, 10, 15, 5, 5, 5, DateTimeKind.Utc)),
689 new JProperty("Test2", "Test2Value"),
690 new JProperty("Test3", null)
693 enumerable = o.AsJEnumerable();
694 Assert.IsNotNull(enumerable);
695 Assert.AreEqual(o, enumerable);
697 DateTime d = enumerable["Test1"].Value<DateTime>();
699 Assert.AreEqual(new DateTime(2000, 10, 15, 5, 5, 5, DateTimeKind.Utc), d);
702 #if !(NET20 || NET35 || SILVERLIGHT)
704 public void CovariantIJEnumerable()
706 IEnumerable<JObject> o = new[]
708 JObject.FromObject(new {First = 1, Second = 2}),
709 JObject.FromObject(new {First = 1, Second = 2})
712 IJEnumerable<JToken> values = o.Properties();
713 Assert.AreEqual(4, values.Count());
718 public void ChildrenExtension()
722 ""title"": ""James Newton-King"",
723 ""link"": ""http://james.newtonking.com"",
724 ""description"": ""James Newton-King's blog."",
727 ""title"": ""Json.NET 1.3 + New license + Now on CodePlex"",
728 ""description"": ""Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex"",
729 ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
736 ""title"": ""LINQ to JSON beta"",
737 ""description"": ""Annoucing LINQ to JSON"",
738 ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
747 ""title"": ""James Newton-King"",
748 ""link"": ""http://james.newtonking.com"",
749 ""description"": ""James Newton-King's blog."",
752 ""title"": ""Json.NET 1.3 + New license + Now on CodePlex"",
753 ""description"": ""Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex"",
754 ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
761 ""title"": ""LINQ to JSON beta"",
762 ""description"": ""Annoucing LINQ to JSON"",
763 ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
773 JArray o = JArray.Parse(json);
775 Assert.AreEqual(4, o.Children()["item"].Children()["title"].Count());
776 CollectionAssert.AreEqual(new string[]
778 "Json.NET 1.3 + New license + Now on CodePlex",
780 "Json.NET 1.3 + New license + Now on CodePlex",
783 o.Children()["item"].Children()["title"].Values<string>().ToArray());