All files
[pithos-ms-client] / trunk / Libraries / Json40r2 / Source / Src / Newtonsoft.Json.Tests / Linq / LinqToJsonTest.cs
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 using System.Collections.Generic;
28 using System.Globalization;
29 using System.Linq;
30 using System.Text;
31 using NUnit.Framework;
32 using Newtonsoft.Json.Linq;
33 using System.Xml;
34 using System.IO;
35 using Newtonsoft.Json.Converters;
36 using Newtonsoft.Json.Tests.TestObjects;
37
38 namespace Newtonsoft.Json.Tests.Linq
39 {
40   public class LinqToJsonTest : TestFixtureBase
41   {
42     [Test]
43     public void DoubleValue()
44     {
45       JArray j = JArray.Parse("[-1E+4,100.0e-2]");
46
47       double value = (double)j[0];
48       Assert.AreEqual(-10000d, value);
49
50       value = (double)j[1];
51       Assert.AreEqual(1d, value);
52     }
53
54     [Test]
55     public void Manual()
56     {
57       JArray array = new JArray();
58       JValue text = new JValue("Manual text");
59       JValue date = new JValue(new DateTime(2000, 5, 23));
60
61       array.Add(text);
62       array.Add(date);
63
64       string json = array.ToString();
65       // [
66       //   "Manual text",
67       //   "\/Date(958996800000+1200)\/"
68       // ]
69     }
70
71     [Test]
72     public void LinqToJsonDeserialize()
73     {
74       JObject o = new JObject(
75         new JProperty("Name", "John Smith"),
76         new JProperty("BirthDate", new DateTime(1983, 3, 20))
77         );
78
79       JsonSerializer serializer = new JsonSerializer();
80       Person p = (Person)serializer.Deserialize(new JTokenReader(o), typeof(Person));
81
82       // John Smith
83       Console.WriteLine(p.Name);
84     }
85
86     [Test]
87     public void ObjectParse()
88     {
89       string json = @"{
90         CPU: 'Intel',
91         Drives: [
92           'DVD read/writer',
93           ""500 gigabyte hard drive""
94         ]
95       }";
96
97       JObject o = JObject.Parse(json);
98       IList<JProperty> properties = o.Properties().ToList();
99
100       Assert.AreEqual("CPU", properties[0].Name);
101       Assert.AreEqual("Intel", (string)properties[0].Value);
102       Assert.AreEqual("Drives", properties[1].Name);
103
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));
108
109       List<object> parameterValues =
110         (from p in o.Properties()
111          where p.Value is JValue
112          select ((JValue)p.Value).Value).ToList();
113
114       Assert.AreEqual(1, parameterValues.Count);
115       Assert.AreEqual("Intel", parameterValues[0]);
116     }
117
118     [Test]
119     public void CreateLongArray()
120     {
121       string json = @"[0,1,2,3,4,5,6,7,8,9]";
122
123       JArray a = JArray.Parse(json);
124       List<int> list = a.Values<int>().ToList();
125
126       List<int> expected = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
127
128       CollectionAssert.AreEqual(expected, list);
129     }
130
131     [Test]
132     public void GoogleSearchAPI()
133     {
134       #region GoogleJson
135       string json = @"{
136     results:
137         [
138             {
139                 GsearchResultClass:""GwebSearch"",
140                 unescapedUrl : ""http://www.google.com/"",
141                 url : ""http://www.google.com/"",
142                 visibleUrl : ""www.google.com"",
143                 cacheUrl : 
144 ""http://www.google.com/search?q=cache:zhool8dxBV4J:www.google.com"",
145                 title : ""Google"",
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.""
150             },
151             {
152                 GsearchResultClass:""GwebSearch"",
153                 unescapedUrl : ""http://news.google.com/"",
154                 url : ""http://news.google.com/"",
155                 visibleUrl : ""news.google.com"",
156                 cacheUrl : 
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.""
161             },
162             
163             {
164                 GsearchResultClass:""GwebSearch"",
165                 unescapedUrl : ""http://groups.google.com/"",
166                 url : ""http://groups.google.com/"",
167                 visibleUrl : ""groups.google.com"",
168                 cacheUrl : 
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 
174 comments.""
175             },
176             
177             {
178                 GsearchResultClass:""GwebSearch"",
179                 unescapedUrl : ""http://maps.google.com/"",
180                 url : ""http://maps.google.com/"",
181                 visibleUrl : ""maps.google.com"",
182                 cacheUrl : 
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.""
189             }
190         ],
191         
192     adResults:
193         [
194             {
195                 GsearchResultClass:""GwebSearch.ad"",
196                 title : ""Gartner Symposium/ITxpo"",
197                 content1 : ""Meet brilliant Gartner IT analysts"",
198                 content2 : ""20-23 May 2007- Barcelona, Spain"",
199                 url : 
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="", 
201
202                 impressionUrl : 
203 ""http://www.google.com/uds/css/ad-indicator-on.gif?ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB"", 
204
205                 unescapedUrl : 
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="", 
207
208                 visibleUrl : ""www.gartner.com""
209             }
210         ]
211 }
212 ";
213       #endregion
214
215       JObject o = JObject.Parse(json);
216
217       List<JObject> resultObjects = o["results"].Children<JObject>().ToList();
218
219       Assert.AreEqual(32, resultObjects.Properties().Count());
220
221       Assert.AreEqual(32, resultObjects.Cast<JToken>().Values().Count());
222
223       Assert.AreEqual(4, resultObjects.Cast<JToken>().Values("GsearchResultClass").Count());
224
225       Assert.AreEqual(5, o.PropertyValues().Cast<JArray>().Children().Count());
226
227       List<string> resultUrls = o["results"].Children().Values<string>("url").ToList();
228
229       List<string> expectedUrls = new List<string>() { "http://www.google.com/", "http://news.google.com/", "http://groups.google.com/", "http://maps.google.com/" };
230
231       CollectionAssert.AreEqual(expectedUrls, resultUrls);
232
233       List<JToken> descendants = o.Descendants().ToList();
234       Assert.AreEqual(89, descendants.Count);
235     }
236
237     [Test]
238     public void JTokenToString()
239     {
240       string json = @"{
241   CPU: 'Intel',
242   Drives: [
243     'DVD read/writer',
244     ""500 gigabyte hard drive""
245   ]
246 }";
247
248       JObject o = JObject.Parse(json);
249
250       Assert.AreEqual(@"{
251   ""CPU"": ""Intel"",
252   ""Drives"": [
253     ""DVD read/writer"",
254     ""500 gigabyte hard drive""
255   ]
256 }", o.ToString());
257
258       JArray list = o.Value<JArray>("Drives");
259
260       Assert.AreEqual(@"[
261   ""DVD read/writer"",
262   ""500 gigabyte hard drive""
263 ]", list.ToString());
264
265       JProperty cpuProperty = o.Property("CPU");
266       Assert.AreEqual(@"""CPU"": ""Intel""", cpuProperty.ToString());
267
268       JProperty drivesProperty = o.Property("Drives");
269       Assert.AreEqual(@"""Drives"": [
270   ""DVD read/writer"",
271   ""500 gigabyte hard drive""
272 ]", drivesProperty.ToString());
273     }
274
275     [Test]
276     public void JTokenToStringTypes()
277     {
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}]}";
279
280       JObject o = JObject.Parse(json);
281
282       Assert.AreEqual(@"""Establised"": new Date(
283   1264118400000
284 )", o.Property("Establised").ToString());
285       Assert.AreEqual(@"new Date(
286   1264118400000
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());
292
293       json = @"[null,undefined]";
294
295       JArray a = JArray.Parse(json);
296       Assert.AreEqual(@"[
297   null,
298   undefined
299 ]", a.ToString());
300       Assert.AreEqual(@"", a.Children().ElementAt(0).ToString());
301       Assert.AreEqual(@"", a.Children().ElementAt(1).ToString());
302     }
303
304     [Test]
305     public void CreateJTokenTree()
306     {
307       JObject o =
308         new JObject(
309           new JProperty("Test1", "Test1Value"),
310           new JProperty("Test2", "Test2Value"),
311           new JProperty("Test3", "Test3Value"),
312           new JProperty("Test4", null)
313         );
314
315       Assert.AreEqual(4, o.Properties().Count());
316
317       Assert.AreEqual(@"{
318   ""Test1"": ""Test1Value"",
319   ""Test2"": ""Test2Value"",
320   ""Test3"": ""Test3Value"",
321   ""Test4"": null
322 }", o.ToString());
323
324       JArray a =
325         new JArray(
326           o,
327           new DateTime(2000, 10, 10, 0, 0, 0, DateTimeKind.Utc),
328           55,
329           new JArray(
330             "1",
331             2,
332             3.0,
333             new DateTime(4, 5, 6, 7, 8, 9, DateTimeKind.Utc)
334           ),
335           new JConstructor(
336             "ConstructorName",
337             "param1",
338             2,
339             3.0
340           )
341         );
342
343       Assert.AreEqual(5, a.Count());
344       Assert.AreEqual(@"[
345   {
346     ""Test1"": ""Test1Value"",
347     ""Test2"": ""Test2Value"",
348     ""Test3"": ""Test3Value"",
349     ""Test4"": null
350   },
351   ""\/Date(971136000000)\/"",
352   55,
353   [
354     ""1"",
355     2,
356     3.0,
357     ""\/Date(-62030076711000)\/""
358   ],
359   new ConstructorName(
360     ""param1"",
361     2,
362     3.0
363   )
364 ]", a.ToString());
365     }
366
367     private class Post
368     {
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; }
373     }
374
375     private List<Post> GetPosts()
376     {
377       return new List<Post>()
378       {
379         new Post()
380         {
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" }
385         },
386         new Post()
387         {
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" }
392         }
393       };
394     }
395
396     [Test]
397     public void CreateJTokenTreeNested()
398     {
399       List<Post> posts = GetPosts();
400
401       JObject rss =
402         new JObject(
403           new JProperty("channel",
404             new JObject(
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",
409                 new JArray(
410                   from p in posts
411                   orderby p.Title
412                   select new JObject(
413                     new JProperty("title", p.Title),
414                     new JProperty("description", p.Description),
415                     new JProperty("link", p.Link),
416                     new JProperty("category",
417                       new JArray(
418                         from c in p.Categories
419                         select new JValue(c)))))))));
420
421       Console.WriteLine(rss.ToString());
422
423       //{
424       //  "channel": {
425       //    "title": "James Newton-King",
426       //    "link": "http://james.newtonking.com",
427       //    "description": "James Newton-King's blog.",
428       //    "item": [
429       //      {
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",
433       //        "category": [
434       //          "Json.NET",
435       //          "CodePlex"
436       //        ]
437       //      },
438       //      {
439       //        "title": "LINQ to JSON beta",
440       //        "description": "Annoucing LINQ to JSON",
441       //        "link": "http://james.newtonking.com/projects/json-net.aspx",
442       //        "category": [
443       //          "Json.NET",
444       //          "LINQ"
445       //        ]
446       //      }
447       //    ]
448       //  }
449       //}
450
451       var postTitles =
452         from p in rss["channel"]["item"]
453         select p.Value<string>("title");
454
455       foreach (var item in postTitles)
456       {
457         Console.WriteLine(item);
458       }
459
460       //LINQ to JSON beta
461       //Json.NET 1.3 + New license + Now on CodePlex
462
463       var categories =
464         from c in rss["channel"]["item"].Children()["category"].Values<string>()
465         group c by c into g
466         orderby g.Count() descending
467         select new { Category = g.Key, Count = g.Count() };
468
469       foreach (var c in categories)
470       {
471         Console.WriteLine(c.Category + " - Count: " + c.Count);
472       }
473
474       //Json.NET - Count: 2
475       //LINQ - Count: 1
476       //CodePlex - Count: 1
477     }
478
479     [Test]
480     public void BasicQuerying()
481     {
482       string json = @"{
483                         ""channel"": {
484                           ""title"": ""James Newton-King"",
485                           ""link"": ""http://james.newtonking.com"",
486                           ""description"": ""James Newton-King's blog."",
487                           ""item"": [
488                             {
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"",
492                               ""category"": [
493                                 ""Json.NET"",
494                                 ""CodePlex""
495                               ]
496                             },
497                             {
498                               ""title"": ""LINQ to JSON beta"",
499                               ""description"": ""Annoucing LINQ to JSON"",
500                               ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
501                               ""category"": [
502                                 ""Json.NET"",
503                                 ""LINQ""
504                               ]
505                             }
506                           ]
507                         }
508                       }";
509
510       JObject o = JObject.Parse(json);
511
512       Assert.AreEqual(null, o["purple"]);
513       Assert.AreEqual(null, o.Value<string>("purple"));
514
515       Assert.IsInstanceOfType(typeof(JArray), o["channel"]["item"]);
516
517       Assert.AreEqual(2, o["channel"]["item"].Children()["title"].Count());
518       Assert.AreEqual(0, o["channel"]["item"].Children()["monkey"].Count());
519
520       Assert.AreEqual("Json.NET 1.3 + New license + Now on CodePlex", (string)o["channel"]["item"][0]["title"]);
521
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());
523     }
524
525     [Test]
526     [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Accessed JObject values with invalid key value: 0. Object property name expected.")]
527     public void JObjectIntIndex()
528     {
529       JObject o = new JObject();
530       Assert.AreEqual(null, o[0]);
531     }
532
533     [Test]
534     [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"Accessed JArray values with invalid key value: ""purple"". Array position index expected.")]
535     public void JArrayStringIndex()
536     {
537       JArray a = new JArray();
538       Assert.AreEqual(null, a["purple"]);
539     }
540
541     [Test]
542     [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"Accessed JConstructor values with invalid key value: ""purple"". Argument position index expected.")]
543     public void JConstructorStringIndex()
544     {
545       JConstructor c = new JConstructor("ConstructorValue");
546       Assert.AreEqual(null, c["purple"]);
547     }
548
549 #if !PocketPC && !NET20
550     [Test]
551     public void ToStringJsonConverter()
552     {
553       JObject o =
554         new JObject(
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)
559         );
560
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);
567
568       string json = sw.ToString();
569
570       Assert.AreEqual(@"{
571   ""Test1"": new Date(
572     971586305000
573   ),
574   ""Test2"": new Date(
575     971546045000
576   ),
577   ""Test3"": ""Test3Value"",
578   ""Test4"": null
579 }", json);
580     }
581
582     [Test]
583     public void DateTimeOffset()
584     {
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)),
590       };
591
592       JsonSerializer jsonSerializer = new JsonSerializer();
593
594       JTokenWriter jsonWriter;
595       using (jsonWriter = new JTokenWriter())
596       {
597         jsonSerializer.Serialize(jsonWriter, testDates);
598       }
599
600       Assert.AreEqual(4, jsonWriter.Token.Children().Count());
601     }
602 #endif
603
604     [Test]
605     public void FromObject()
606     {
607       List<Post> posts = GetPosts();
608
609       JObject o = JObject.FromObject(new
610       {
611         channel = new
612         {
613           title = "James Newton-King",
614           link = "http://james.newtonking.com",
615           description = "James Newton-King's blog.",
616           item =
617               from p in posts
618               orderby p.Title
619               select new
620               {
621                 title = p.Title,
622                 description = p.Description,
623                 link = p.Link,
624                 category = p.Categories
625               }
626         }
627       });
628
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());
634
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());
638     }
639
640     [Test]
641     public void FromAnonDictionary()
642     {
643       List<Post> posts = GetPosts();
644
645       JObject o = JObject.FromObject(new
646       {
647         channel = new Dictionary<string, object>
648         {
649           { "title", "James Newton-King" },
650           { "link", "http://james.newtonking.com" },
651           { "description", "James Newton-King's blog." },
652           { "item", 
653                   (from p in posts
654                   orderby p.Title
655                   select new
656                   {
657                     title = p.Title,
658                     description = p.Description,
659                     link = p.Link,
660                     category = p.Categories
661                   })
662           }
663         }
664       });
665
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());
671
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());
675     }
676
677     [Test]
678     public void AsJEnumerable()
679     {
680       JObject o = null;
681       IJEnumerable<JToken> enumerable = null;
682
683       enumerable = o.AsJEnumerable();
684       Assert.IsNull(enumerable);
685     
686       o =
687         new JObject(
688           new JProperty("Test1", new DateTime(2000, 10, 15, 5, 5, 5, DateTimeKind.Utc)),
689           new JProperty("Test2", "Test2Value"),
690           new JProperty("Test3", null)
691         );
692
693       enumerable = o.AsJEnumerable();
694       Assert.IsNotNull(enumerable);
695       Assert.AreEqual(o, enumerable);
696
697       DateTime d = enumerable["Test1"].Value<DateTime>();
698
699       Assert.AreEqual(new DateTime(2000, 10, 15, 5, 5, 5, DateTimeKind.Utc), d);
700     }
701
702 #if !(NET20 || NET35 || SILVERLIGHT)
703     [Test]
704     public void CovariantIJEnumerable()
705     {
706       IEnumerable<JObject> o = new[]
707         {
708           JObject.FromObject(new {First = 1, Second = 2}),
709           JObject.FromObject(new {First = 1, Second = 2})
710         };
711
712       IJEnumerable<JToken> values = o.Properties();
713       Assert.AreEqual(4, values.Count());
714     }
715 #endif
716
717     [Test]
718     public void ChildrenExtension()
719     {
720       string json = @"[
721                         {
722                           ""title"": ""James Newton-King"",
723                           ""link"": ""http://james.newtonking.com"",
724                           ""description"": ""James Newton-King's blog."",
725                           ""item"": [
726                             {
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"",
730                               ""category"": [
731                                 ""Json.NET"",
732                                 ""CodePlex""
733                               ]
734                             },
735                             {
736                               ""title"": ""LINQ to JSON beta"",
737                               ""description"": ""Annoucing LINQ to JSON"",
738                               ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
739                               ""category"": [
740                                 ""Json.NET"",
741                                 ""LINQ""
742                               ]
743                             }
744                           ]
745                         },
746                         {
747                           ""title"": ""James Newton-King"",
748                           ""link"": ""http://james.newtonking.com"",
749                           ""description"": ""James Newton-King's blog."",
750                           ""item"": [
751                             {
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"",
755                               ""category"": [
756                                 ""Json.NET"",
757                                 ""CodePlex""
758                               ]
759                             },
760                             {
761                               ""title"": ""LINQ to JSON beta"",
762                               ""description"": ""Annoucing LINQ to JSON"",
763                               ""link"": ""http://james.newtonking.com/projects/json-net.aspx"",
764                               ""category"": [
765                                 ""Json.NET"",
766                                 ""LINQ""
767                               ]
768                             }
769                           ]
770                         }
771                       ]";
772
773       JArray o = JArray.Parse(json);
774
775       Assert.AreEqual(4, o.Children()["item"].Children()["title"].Count());
776       CollectionAssert.AreEqual(new string[]
777         {
778           "Json.NET 1.3 + New license + Now on CodePlex",
779           "LINQ to JSON beta",
780           "Json.NET 1.3 + New license + Now on CodePlex",
781           "LINQ to JSON beta"
782         },
783         o.Children()["item"].Children()["title"].Values<string>().ToArray());
784     }
785   }
786 }