Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Linq\JToken.cs

Symbol Coverage: 91.39% (308 of 337)

Branch Coverage: 81.36% (227 of 279)

Cyclomatic Complexity Avg: 2.05 Max:8

Code Lines: 333


L V Source
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.Linq;
29
using System.IO;
30
using Newtonsoft.Json.Utilities;
31
using System.Diagnostics;
32
using System.Globalization;
33
using System.Collections;
34
using System.ComponentModel;
35

  
36
namespace Newtonsoft.Json.Linq
37
{
38
  /// <summary>
39
  /// Represents an abstract JSON token.
40
  /// </summary>
41
  public abstract class JToken : IJEnumerable<JToken>, IJsonLineInfo
42
  {
43
    private JContainer _parent;
44
    internal JToken _next;
45
    private static JTokenEqualityComparer _equalityComparer;
46

  
47
    private int? _lineNumber;
48
    private int? _linePosition;
49

  
50
    /// <summary>
51
    /// Gets a comparer that can compare two tokens for value equality.
52
    /// </summary>
53
    /// <value>A <see cref="JTokenEqualityComparer"/> that can compare two nodes for value equality.</value>
54
    public static JTokenEqualityComparer EqualityComparer
55
    {
56
      get
57
      {
58
 4
        if (_equalityComparer == null)
59
 1
          _equalityComparer = new JTokenEqualityComparer();
60

  
61
 4
        return _equalityComparer;
62
 4
      }
63
    }
64

  
65
    /// <summary>
66
    /// Gets or sets the parent.
67
    /// </summary>
68
    /// <value>The parent.</value>
69
    public JContainer Parent
70
    {
71
      [DebuggerStepThrough]
72
 11596
      get { return _parent; }
73
 2045
      internal set { _parent = value; }
74
    }
75

  
76
    /// <summary>
77
    /// Gets the root <see cref="JToken"/> of this <see cref="JToken"/>.
78
    /// </summary>
79
    /// <value>The root <see cref="JToken"/> of this <see cref="JToken"/>.</value>
80
    public JToken Root
81
    {
82
      get
83
      {
84
 4
        JContainer parent = Parent;
85
 4
        if (parent == null)
86
 2
          return this;
87

  
88
 3
        while (parent.Parent != null)
89
        {
90
 1
          parent = parent.Parent;
91
        }
92

  
93
 2
        return parent;
94
 4
      }
95
    }
96

  
97
    internal abstract JToken CloneToken();
98
    internal abstract bool DeepEquals(JToken node);
99

  
100
    /// <summary>
101
    /// Gets the node type for this <see cref="JToken"/>.
102
    /// </summary>
103
    /// <value>The type.</value>
104
    public abstract JTokenType Type { get; }
105

  
106
    /// <summary>
107
    /// Gets a value indicating whether this token has childen tokens.
108
    /// </summary>
109
    /// <value>
110
    /// 	<c>true</c> if this token has child values; otherwise, <c>false</c>.
111
    /// </value>
112
    public abstract bool HasValues { get; }
113

  
114
    /// <summary>
115
    /// Compares the values of two tokens, including the values of all descendant tokens.
116
    /// </summary>
117
    /// <param name="t1">The first <see cref="JToken"/> to compare.</param>
118
    /// <param name="t2">The second <see cref="JToken"/> to compare.</param>
119
    /// <returns>true if the tokens are equal; otherwise false.</returns>
120
    public static bool DeepEquals(JToken t1, JToken t2)
121
    {
122
 109
      return (t1 == t2 || (t1 != null && t2 != null && t1.DeepEquals(t2)));
123
 109
    }
124

  
125
    /// <summary>
126
    /// Gets the next sibling token of this node.
127
    /// </summary>
128
    /// <value>The <see cref="JToken"/> that contains the next sibling token.</value>
129
    public JToken Next
130
    {
131
      get
132
      {
133
 4269
        if (_parent != null && _next != _parent.First)
134
 2765
          return _next;
135

  
136
 1504
        return null;
137
 4269
      }
138
 2825
      internal set { _next = value; }
139
    }
140

  
141
    /// <summary>
142
    /// Gets the previous sibling token of this node.
143
    /// </summary>
144
    /// <value>The <see cref="JToken"/> that contains the previous sibling token.</value>
145
    public JToken Previous
146
    {
147
      get
148
      {
149
 15
        if (_parent == null)
150
 3
          return null;
151

  
152
 12
        JToken parentNext = _parent.Content._next;
153
 12
        JToken parentNextBefore = null;
154
 29
        while (parentNext != this)
155
        {
156
 17
          parentNextBefore = parentNext;
157
 17
          parentNext = parentNext.Next;
158
        }
159
 12
        return parentNextBefore;
160
 15
      }
161
    }
162

  
163
 2697
    internal JToken()
164
    {
165
 2697
    }
166

  
167
    /// <summary>
168
    /// Adds the specified content immediately after this token.
169
    /// </summary>
170
    /// <param name="content">A content object that contains simple content or a collection of content objects to be added after this token.</param>
171
    public void AddAfterSelf(object content)
172
    {
173
 2
      if (_parent == null)
174
 0
        throw new InvalidOperationException("The parent is missing.");
175

  
176
 2
      _parent.AddInternal((Next == null), this, content);
177
 2
    }
178

  
179
    /// <summary>
180
    /// Adds the specified content immediately before this token.
181
    /// </summary>
182
    /// <param name="content">A content object that contains simple content or a collection of content objects to be added before this token.</param>
183
    public void AddBeforeSelf(object content)
184
    {
185
 3
      if (_parent == null)
186
 0
        throw new InvalidOperationException("The parent is missing.");
187

  
188
 3
      JToken previous = Previous;
189
 3
      if (previous == null)
190
 1
        previous = _parent.Last;
191

  
192
 3
      _parent.AddInternal(false, previous, content);
193
 3
    }
194

  
195
    /// <summary>
196
    /// Returns a collection of the ancestor tokens of this token.
197
    /// </summary>
198
    /// <returns>A collection of the ancestor tokens of this token.</returns>
199
    public IEnumerable<JToken> Ancestors()
200
    {
201
 1
      for (JToken parent = Parent; parent != null; parent = parent.Parent)
202
      {
203
 2
        yield return parent;
204
      }
205
    }
206

  
207
    /// <summary>
208
    /// Returns a collection of the sibling tokens after this token, in document order.
209
    /// </summary>
210
    /// <returns>A collection of the sibling tokens after this tokens, in document order.</returns>
211
    public IEnumerable<JToken> AfterSelf()
212
    {
213
 1
      if (Parent == null)
214
 0
        yield break;
215

  
216
 1
      for (JToken o = Next; o != null; o = o.Next)
217
 2
        yield return o;
218
    }
219

  
220
    /// <summary>
221
    /// Returns a collection of the sibling tokens before this token, in document order.
222
    /// </summary>
223
    /// <returns>A collection of the sibling tokens before this token, in document order.</returns>
224
    public IEnumerable<JToken> BeforeSelf()
225
    {
226
 2
      for (JToken o = Parent.First; o != this; o = o.Next)
227
 4
        yield return o;
228
    }
229

  
230
    /// <summary>
231
    /// Gets the <see cref="JToken"/> with the specified key.
232
    /// </summary>
233
    /// <value>The <see cref="JToken"/> with the specified key.</value>
234
    public virtual JToken this[object key]
235
    {
236
 1
      get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
237
 1
      set { throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
238
    }
239

  
240
    /// <summary>
241
    /// Gets the <see cref="JToken"/> with the specified key converted to the specified type.
242
    /// </summary>
243
    /// <typeparam name="T">The type to convert the token to.</typeparam>
244
    /// <param name="key">The token key.</param>
245
    /// <returns>The converted token value.</returns>
246
    public virtual T Value<T>(object key)
247
    {
248
 6
      JToken token = this[key];
249

  
250
 6
      return Extensions.Convert<JToken, T>(token);
251
 6
    }
252

  
253
    /// <summary>
254
    /// Get the first child token of this token.
255
    /// </summary>
256
    /// <value>A <see cref="JToken"/> containing the first child token of the <see cref="JToken"/>.</value>
257
    public virtual JToken First
258
    {
259
 1
      get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
260
    }
261

  
262
    /// <summary>
263
    /// Get the last child token of this token.
264
    /// </summary>
265
    /// <value>A <see cref="JToken"/> containing the last child token of the <see cref="JToken"/>.</value>
266
    public virtual JToken Last
267
    {
268
 1
      get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
269
    }
270

  
271
    /// <summary>
272
    /// Returns a collection of the child tokens of this token, in document order.
273
    /// </summary>
274
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> containing the child tokens of this <see cref="JToken"/>, in document order.</returns>
275
    public virtual JEnumerable<JToken> Children()
276
    {
277
 1
      throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
278
    }
279

  
280
    /// <summary>
281
    /// Returns a collection of the child tokens of this token, in document order, filtered by the specified type.
282
    /// </summary>
283
    /// <typeparam name="T">The type to filter the child tokens on.</typeparam>
284
    /// <returns>A <see cref="JEnumerable{T}"/> containing the child tokens of this <see cref="JToken"/>, in document order.</returns>
285
    public JEnumerable<T> Children<T>() where T : JToken
286
    {
287
 2
      return new JEnumerable<T>(Children().OfType<T>());
288
 2
    }
289

  
290
    /// <summary>
291
    /// Returns a collection of the child values of this token, in document order.
292
    /// </summary>
293
    /// <typeparam name="T">The type to convert the values to.</typeparam>
294
    /// <returns>A <see cref="IEnumerable{T}"/> containing the child values of this <see cref="JToken"/>, in document order.</returns>
295
    public virtual IEnumerable<T> Values<T>()
296
    {
297
 1
      throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
298
    }
299

  
300
    /// <summary>
301
    /// Removes this token from its parent.
302
    /// </summary>
303
    public void Remove()
304
    {
305
 12
      if (_parent == null)
306
 1
        throw new InvalidOperationException("The parent is missing.");
307

  
308
 11
      _parent.RemoveItem(this);
309
 11
    }
310

  
311
    /// <summary>
312
    /// Replaces this token with the specified token.
313
    /// </summary>
314
    /// <param name="value">The value.</param>
315
    public void Replace(JToken value)
316
    {
317
 31
      if (_parent == null)
318
 0
        throw new InvalidOperationException("The parent is missing.");
319

  
320
 31
      _parent.ReplaceItem(this, value);
321
 28
    }
322

  
323
    /// <summary>
324
    /// Writes this token to a <see cref="JsonWriter"/>.
325
    /// </summary>
326
    /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
327
    /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
328
    public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters);
329

  
330
    /// <summary>
331
    /// Returns the indented JSON for this token.
332
    /// </summary>
333
    /// <returns>
334
    /// The indented JSON for this token.
335
    /// </returns>
336
    public override string ToString()
337
    {
338
 46
      return ToString(Formatting.Indented);
339
 46
    }
340

  
341
    /// <summary>
342
    /// Returns the JSON for this token using the given formatting and converters.
343
    /// </summary>
344
    /// <param name="formatting">Indicates how the output is formatted.</param>
345
    /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
346
    /// <returns>The JSON for this token using the given formatting and converters.</returns>
347
    public string ToString(Formatting formatting, params JsonConverter[] converters)
348
    {
349
 48
      using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
350
      {
351
 48
        JsonTextWriter jw = new JsonTextWriter(sw);
352
 48
        jw.Formatting = formatting;
353

  
354
 48
        WriteTo(jw, converters);
355

  
356
 48
        return sw.ToString();
357
      }
358
 48
    }
359

  
360
    private static JValue EnsureValue(JToken value)
361
    {
362
 190
      if (value == null)
363
 0
        throw new ArgumentNullException("value");
364

  
365
 190
      if (value is JProperty)
366
 2
        value = ((JProperty)value).Value;
367

  
368
 190
      JValue v = value as JValue;
369

  
370
 190
      return v;
371
 190
    }
372

  
373
    private static string GetType(JToken token)
374
    {
375
 3
      ValidationUtils.ArgumentNotNull(token, "token");
376

  
377
 3
      if (token is JProperty)
378
 1
        token = ((JProperty)token).Value;
379

  
380
 3
      return token.Type.ToString();
381
 3
    }
382

  
383
    private static bool IsNullable(JToken o)
384
    {
385
 15
      return (o.Type == JTokenType.Undefined || o.Type == JTokenType.Null);
386
 15
    }
387

  
388
    private static bool ValidateFloat(JToken o, bool nullable)
389
    {
390
 23
      return (o.Type == JTokenType.Float || o.Type == JTokenType.Integer || (nullable && IsNullable(o)));
391
 23
    }
392

  
393
    private static bool ValidateInteger(JToken o, bool nullable)
394
    {
395
 79
      return (o.Type == JTokenType.Integer || (nullable && IsNullable(o)));
396
 79
    }
397

  
398
    private static bool ValidateDate(JToken o, bool nullable)
399
    {
400
 8
      return (o.Type == JTokenType.Date || (nullable && IsNullable(o)));
401
 8
    }
402

  
403
    private static bool ValidateBoolean(JToken o, bool nullable)
404
    {
405
 6
      return (o.Type == JTokenType.Boolean || (nullable && IsNullable(o)));
406
 6
    }
407

  
408
    private static bool ValidateString(JToken o)
409
    {
410
 70
      return (o.Type == JTokenType.String || o.Type == JTokenType.Comment || o.Type == JTokenType.Raw || IsNullable(o));
411
 70
    }
412

  
413
    private static bool ValidateBytes(JToken o)
414
    {
415
 2
      return (o.Type == JTokenType.Bytes || IsNullable(o));
416
 2
    }
417

  
418
    #region Cast from operators
419
    /// <summary>
420
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Boolean"/>.
421
    /// </summary>
422
    /// <param name="value">The value.</param>
423
    /// <returns>The result of the conversion.</returns>
424
    public static explicit operator bool(JToken value)
425
    {
426
 4
      JValue v = EnsureValue(value);
427
 4
      if (v == null || !ValidateBoolean(v, false))
428
 0
        throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
429

  
430
 4
      return (bool)v.Value;
431
 4
    }
432

  
433
#if !PocketPC && !NET20
434
    /// <summary>
435
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.DateTimeOffset"/>.
436
    /// </summary>
437
    /// <param name="value">The value.</param>
438
    /// <returns>The result of the conversion.</returns>
439
    public static explicit operator DateTimeOffset(JToken value)
440
    {
441
 1
      JValue v = EnsureValue(value);
442
 1
      if (v == null || !ValidateDate(v, false))
443
 0
        throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
444

  
445
 1
      return (DateTimeOffset)v.Value;
446
 1
    }
447
#endif
448

  
449
    /// <summary>
450
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Boolean}"/>.
451
    /// </summary>
452
    /// <param name="value">The value.</param>
453
    /// <returns>The result of the conversion.</returns>
454
    public static explicit operator bool?(JToken value)
455
    {
456
 3
      if (value == null)
457
 1
        return null;
458

  
459
 2
      JValue v = EnsureValue(value);
460
 2
      if (v == null || !ValidateBoolean(v, true))
461
 0
        throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
462

  
463
 2
      return (bool?)v.Value;
464
 3
    }
465

  
466
    /// <summary>
467
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Int64"/>.
468
    /// </summary>
469
    /// <param name="value">The value.</param>
470
    /// <returns>The result of the conversion.</returns>
471
    public static explicit operator long(JToken value)
472
    {
473
 1
      JValue v = EnsureValue(value);
474
 1
      if (v == null || !ValidateInteger(v, false))
475
 0
        throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
476

  
477
 1
      return (long)v.Value;
478
 1
    }
479

  
480
    /// <summary>
481
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{DateTime}"/>.
482
    /// </summary>
483
    /// <param name="value">The value.</param>
484
    /// <returns>The result of the conversion.</returns>
485
    public static explicit operator DateTime?(JToken value)
486
    {
487
 2
      if (value == null)
488
 1
        return null;
489

  
490
 1
      JValue v = EnsureValue(value);
491
 1
      if (v == null || !ValidateDate(v, true))
492
 0
        throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
493

  
494
 1
      return (DateTime?)v.Value;
495
 2
    }
496

  
497
#if !PocketPC && !NET20
498
    /// <summary>
499
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{DateTimeOffset}"/>.
500
    /// </summary>
501
    /// <param name="value">The value.</param>
502
    /// <returns>The result of the conversion.</returns>
503
    public static explicit operator DateTimeOffset?(JToken value)
504
    {
505
 2
      if (value == null)
506
 1
        return null;
507

  
508
 1
      JValue v = EnsureValue(value);
509
 1
      if (v == null || !ValidateDate(v, true))
510
 0
        throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
511

  
512
 1
      return (DateTimeOffset?)v.Value;
513
 2
    }
514
#endif
515

  
516
    /// <summary>
517
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Decimal}"/>.
518
    /// </summary>
519
    /// <param name="value">The value.</param>
520
    /// <returns>The result of the conversion.</returns>
521
    public static explicit operator decimal?(JToken value)
522
    {
523
 3
      if (value == null)
524
 1
        return null;
525

  
526
 2
      JValue v = EnsureValue(value);
527
 2
      if (v == null || !ValidateFloat(v, true))
528
 0
        throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
529

  
530
 2
      return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null;
531
 3
    }
532

  
533
    /// <summary>
534
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Double}"/>.
535
    /// </summary>
536
    /// <param name="value">The value.</param>
537
    /// <returns>The result of the conversion.</returns>
538
    public static explicit operator double?(JToken value)
539
    {
540
 2
      if (value == null)
541
 1
        return null;
542

  
543
 1
      JValue v = EnsureValue(value);
544
 1
      if (v == null || !ValidateFloat(v, true))
545
 0
        throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
546

  
547
 1
      return (double?)v.Value;
548
 2
    }
549

  
550
    /// <summary>
551
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Int32"/>.
552
    /// </summary>
553
    /// <param name="value">The value.</param>
554
    /// <returns>The result of the conversion.</returns>
555
    public static explicit operator int(JToken value)
556
    {
557
 68
      JValue v = EnsureValue(value);
558
 68
      if (v == null || !ValidateInteger(v, false))
559
 1
        throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
560

  
561
 67
      return Convert.ToInt32(v.Value, CultureInfo.InvariantCulture);
562
 67
    }
563

  
564
    /// <summary>
565
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Int32}"/>.
566
    /// </summary>
567
    /// <param name="value">The value.</param>
568
    /// <returns>The result of the conversion.</returns>
569
    public static explicit operator int?(JToken value)
570
    {
571
 6
      if (value == null)
572
 3
        return null;
573

  
574
 3
      JValue v = EnsureValue(value);
575
 3
      if (v == null || !ValidateInteger(v, true))
576
 0
        throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
577

  
578
 3
      return (v.Value != null) ? (int?)Convert.ToInt32(v.Value, CultureInfo.InvariantCulture) : null;
579
 6
    }
580

  
581
    /// <summary>
582
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.DateTime"/>.
583
    /// </summary>
584
    /// <param name="value">The value.</param>
585
    /// <returns>The result of the conversion.</returns>
586
    public static explicit operator DateTime(JToken value)
587
    {
588
 5
      JValue v = EnsureValue(value);
589
 5
      if (v == null || !ValidateDate(v, false))
590
 0
        throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
591

  
592
 5
      return (DateTime)v.Value;
593
 5
    }
594

  
595
    /// <summary>
596
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Int64}"/>.
597
    /// </summary>
598
    /// <param name="value">The value.</param>
599
    /// <returns>The result of the conversion.</returns>
600
    public static explicit operator long?(JToken value)
601
    {
602
 2
      if (value == null)
603
 1
        return null;
604

  
605
 1
      JValue v = EnsureValue(value);
606
 1
      if (v == null || !ValidateInteger(v, true))
607
 0
        throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
608

  
609
 1
      return (long?)v.Value;
610
 2
    }
611

  
612
    /// <summary>
613
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Single}"/>.
614
    /// </summary>
615
    /// <param name="value">The value.</param>
616
    /// <returns>The result of the conversion.</returns>
617
    public static explicit operator float?(JToken value)
618
    {
619
 3
      if (value == null)
620
 1
        return null;
621

  
622
 2
      JValue v = EnsureValue(value);
623
 2
      if (v == null || !ValidateFloat(v, true))
624
 0
        throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
625

  
626
 2
      return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null;
627
 3
    }
628

  
629
    /// <summary>
630
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Decimal"/>.
631
    /// </summary>
632
    /// <param name="value">The value.</param>
633
    /// <returns>The result of the conversion.</returns>
634
    public static explicit operator decimal(JToken value)
635
    {
636
 6
      JValue v = EnsureValue(value);
637
 6
      if (v == null || !ValidateFloat(v, false))
638
 0
        throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
639

  
640
 6
      return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture);
641
 6
    }
642

  
643
    /// <summary>
644
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{UInt32}"/>.
645
    /// </summary>
646
    /// <param name="value">The value.</param>
647
    /// <returns>The result of the conversion.</returns>
648
    public static explicit operator uint?(JToken value)
649
    {
650
 4
      if (value == null)
651
 2
        return null;
652

  
653
 2
      JValue v = EnsureValue(value);
654
 2
      if (v == null || !ValidateInteger(v, true))
655
 0
        throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
656

  
657
 2
      return (uint?)v.Value;
658
 4
    }
659

  
660
    /// <summary>
661
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{UInt64}"/>.
662
    /// </summary>
663
    /// <param name="value">The value.</param>
664
    /// <returns>The result of the conversion.</returns>
665
    public static explicit operator ulong?(JToken value)
666
    {
667
 2
      if (value == null)
668
 1
        return null;
669

  
670
 1
      JValue v = EnsureValue(value);
671
 1
      if (v == null || !ValidateInteger(v, true))
672
 0
        throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
673

  
674
 1
      return (ulong?)v.Value;
675
 2
    }
676

  
677
    /// <summary>
678
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Double"/>.
679
    /// </summary>
680
    /// <param name="value">The value.</param>
681
    /// <returns>The result of the conversion.</returns>
682
    public static explicit operator double(JToken value)
683
    {
684
 8
      JValue v = EnsureValue(value);
685
 8
      if (v == null || !ValidateFloat(v, false))
686
 0
        throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
687

  
688
 8
      return (double)v.Value;
689
 8
    }
690

  
691
    /// <summary>
692
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Single"/>.
693
    /// </summary>
694
    /// <param name="value">The value.</param>
695
    /// <returns>The result of the conversion.</returns>
696
    public static explicit operator float(JToken value)
697
    {
698
 4
      JValue v = EnsureValue(value);
699
 4
      if (v == null || !ValidateFloat(v, false))
700
 0
        throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
701

  
702
 4
      return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture);
703
 4
    }
704

  
705
    /// <summary>
706
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.String"/>.
707
    /// </summary>
708
    /// <param name="value">The value.</param>
709
    /// <returns>The result of the conversion.</returns>
710
    public static explicit operator string(JToken value)
711
    {
712
 74
      if (value == null)
713
 2
        return null;
714

  
715
 72
      JValue v = EnsureValue(value);
716
 72
      if (v == null || !ValidateString(v))
717
 2
        throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
718

  
719
 70
      return (string)v.Value;
720
 72
    }
721

  
722
    /// <summary>
723
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.UInt32"/>.
724
    /// </summary>
725
    /// <param name="value">The value.</param>
726
    /// <returns>The result of the conversion.</returns>
727
    public static explicit operator uint(JToken value)
728
    {
729
 1
      JValue v = EnsureValue(value);
730
 1
      if (v == null || !ValidateInteger(v, false))
731
 0
        throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
732

  
733
 1
      return Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture);
734
 1
    }
735

  
736
    /// <summary>
737
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.UInt64"/>.
738
    /// </summary>
739
    /// <param name="value">The value.</param>
740
    /// <returns>The result of the conversion.</returns>
741
    public static explicit operator ulong(JToken value)
742
    {
743
 2
      JValue v = EnsureValue(value);
744
 2
      if (v == null || !ValidateInteger(v, false))
745
 0
        throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
746

  
747
 2
      return Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture);
748
 2
    }
749

  
750
    /// <summary>
751
    /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Byte[]"/>.
752
    /// </summary>
753
    /// <param name="value">The value.</param>
754
    /// <returns>The result of the conversion.</returns>
755
    public static explicit operator byte[](JToken value)
756
    {
757
 2
      JValue v = EnsureValue(value);
758
 2
      if (v == null || !ValidateBytes(v))
759
 0
        throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
760

  
761
 2
      return (byte[])v.Value;
762
 2
    }
763
    #endregion
764

  
765
    #region Cast to operators
766
    /// <summary>
767
    /// Performs an implicit conversion from <see cref="Boolean"/> to <see cref="JToken"/>.
768
    /// </summary>
769
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
770
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
771
    public static implicit operator JToken(bool value)
772
    {
773
 1
      return new JValue(value);
774
 1
    }
775

  
776
#if !PocketPC && !NET20
777
    /// <summary>
778
    /// Performs an implicit conversion from <see cref="DateTimeOffset"/> to <see cref="JToken"/>.
779
    /// </summary>
780
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
781
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
782
    public static implicit operator JToken(DateTimeOffset value)
783
    {
784
 1
      return new JValue(value);
785
 1
    }
786
#endif
787

  
788
    /// <summary>
789
    /// Performs an implicit conversion from <see cref="Nullable{Boolean}"/> to <see cref="JToken"/>.
790
    /// </summary>
791
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
792
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
793
    public static implicit operator JToken(bool? value)
794
    {
795
 3
      return new JValue(value);
796
 3
    }
797

  
798
    /// <summary>
799
    /// Performs an implicit conversion from <see cref="Nullable{Int64}"/> to <see cref="JToken"/>.
800
    /// </summary>
801
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
802
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
803
    public static implicit operator JToken(long value)
804
    {
805
 1
      return new JValue(value);
806
 1
    }
807

  
808
    /// <summary>
809
    /// Performs an implicit conversion from <see cref="Nullable{DateTime}"/> to <see cref="JToken"/>.
810
    /// </summary>
811
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
812
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
813
    public static implicit operator JToken(DateTime? value)
814
    {
815
 2
      return new JValue(value);
816
 2
    }
817

  
818
#if !PocketPC && !NET20
819
    /// <summary>
820
    /// Performs an implicit conversion from <see cref="Nullable{DateTimeOffset}"/> to <see cref="JToken"/>.
821
    /// </summary>
822
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
823
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
824
    public static implicit operator JToken(DateTimeOffset? value)
825
    {
826
 1
      return new JValue(value);
827
 1
    }
828
#endif
829

  
830
    /// <summary>
831
    /// Performs an implicit conversion from <see cref="Nullable{Decimal}"/> to <see cref="JToken"/>.
832
    /// </summary>
833
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
834
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
835
    public static implicit operator JToken(decimal? value)
836
    {
837
 2
      return new JValue(value);
838
 2
    }
839

  
840
    /// <summary>
841
    /// Performs an implicit conversion from <see cref="Nullable{Double}"/> to <see cref="JToken"/>.
842
    /// </summary>
843
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
844
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
845
    public static implicit operator JToken(double? value)
846
    {
847
 3
      return new JValue(value);
848
 3
    }
849

  
850
    /// <summary>
851
    /// Performs an implicit conversion from <see cref="UInt16"/> to <see cref="JToken"/>.
852
    /// </summary>
853
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
854
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
855
    public static implicit operator JToken(ushort value)
856
    {
857
 1
      return new JValue(value);
858
 1
    }
859

  
860
    /// <summary>
861
    /// Performs an implicit conversion from <see cref="Int32"/> to <see cref="JToken"/>.
862
    /// </summary>
863
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
864
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
865
    public static implicit operator JToken(int value)
866
    {
867
 5
      return new JValue(value);
868
 5
    }
869

  
870
    /// <summary>
871
    /// Performs an implicit conversion from <see cref="Nullable{Int32}"/> to <see cref="JToken"/>.
872
    /// </summary>
873
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
874
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
875
    public static implicit operator JToken(int? value)
876
    {
877
 3
      return new JValue(value);
878
 3
    }
879

  
880
    /// <summary>
881
    /// Performs an implicit conversion from <see cref="DateTime"/> to <see cref="JToken"/>.
882
    /// </summary>
883
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
884
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
885
    public static implicit operator JToken(DateTime value)
886
    {
887
 2
      return new JValue(value);
888
 2
    }
889

  
890
    /// <summary>
891
    /// Performs an implicit conversion from <see cref="Nullable{Int64}"/> to <see cref="JToken"/>.
892
    /// </summary>
893
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
894
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
895
    public static implicit operator JToken(long? value)
896
    {
897
 1
      return new JValue(value);
898
 1
    }
899

  
900
    /// <summary>
901
    /// Performs an implicit conversion from <see cref="Nullable{Single}"/> to <see cref="JToken"/>.
902
    /// </summary>
903
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
904
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
905
    public static implicit operator JToken(float? value)
906
    {
907
 1
      return new JValue(value);
908
 1
    }
909

  
910
    /// <summary>
911
    /// Performs an implicit conversion from <see cref="Decimal"/> to <see cref="JToken"/>.
912
    /// </summary>
913
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
914
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
915
    public static implicit operator JToken(decimal value)
916
    {
917
 2
      return new JValue(value);
918
 2
    }
919

  
920
    /// <summary>
921
    /// Performs an implicit conversion from <see cref="Nullable{UInt16}"/> to <see cref="JToken"/>.
922
    /// </summary>
923
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
924
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
925
    public static implicit operator JToken(ushort? value)
926
    {
927
 1
      return new JValue(value);
928
 1
    }
929

  
930
    /// <summary>
931
    /// Performs an implicit conversion from <see cref="Nullable{UInt32}"/> to <see cref="JToken"/>.
932
    /// </summary>
933
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
934
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
935
    public static implicit operator JToken(uint? value)
936
    {
937
 1
      return new JValue(value);
938
 1
    }
939

  
940
    /// <summary>
941
    /// Performs an implicit conversion from <see cref="Nullable{UInt64}"/> to <see cref="JToken"/>.
942
    /// </summary>
943
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
944
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
945
    public static implicit operator JToken(ulong? value)
946
    {
947
 1
      return new JValue(value);
948
 1
    }
949

  
950
    /// <summary>
951
    /// Performs an implicit conversion from <see cref="Double"/> to <see cref="JToken"/>.
952
    /// </summary>
953
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
954
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
955
    public static implicit operator JToken(double value)
956
    {
957
 1
      return new JValue(value);
958
 1
    }
959

  
960
    /// <summary>
961
    /// Performs an implicit conversion from <see cref="Single"/> to <see cref="JToken"/>.
962
    /// </summary>
963
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
964
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
965
    public static implicit operator JToken(float value)
966
    {
967
 2
      return new JValue(value);
968
 2
    }
969

  
970
    /// <summary>
971
    /// Performs an implicit conversion from <see cref="String"/> to <see cref="JToken"/>.
972
    /// </summary>
973
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
974
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
975
    public static implicit operator JToken(string value)
976
    {
977
 13
      return new JValue(value);
978
 13
    }
979

  
980
    /// <summary>
981
    /// Performs an implicit conversion from <see cref="UInt32"/> to <see cref="JToken"/>.
982
    /// </summary>
983
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
984
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
985
    public static implicit operator JToken(uint value)
986
    {
987
 1
      return new JValue(value);
988
 1
    }
989

  
990
    /// <summary>
991
    /// Performs an implicit conversion from <see cref="UInt64"/> to <see cref="JToken"/>.
992
    /// </summary>
993
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
994
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
995
    public static implicit operator JToken(ulong value)
996
    {
997
 2
      return new JValue(value);
998
 2
    }
999

  
1000
    /// <summary>
1001
    /// Performs an implicit conversion from <see cref="T:System.Byte[]"/> to <see cref="Newtonsoft.Json.Linq.JToken"/>.
1002
    /// </summary>
1003
    /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
1004
    /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
1005
    public static implicit operator JToken(byte[] value)
1006
    {
1007
 3
      return new JValue(value);
1008
 3
    }
1009
    #endregion
1010

  
1011
    IEnumerator IEnumerable.GetEnumerator()
1012
    {
1013
 200
      return ((IEnumerable<JToken>)this).GetEnumerator();
1014
 200
    }
1015

  
1016
    IEnumerator<JToken> IEnumerable<JToken>.GetEnumerator()
1017
    {
1018
 209
      return Children().GetEnumerator();
1019
 209
    }
1020

  
1021
    internal abstract int GetDeepHashCode();
1022

  
1023
    IJEnumerable<JToken> IJEnumerable<JToken>.this[object key]
1024
    {
1025
 1
      get { return this[key]; }
1026
    }
1027

  
1028
    /// <summary>
1029
    /// Creates an <see cref="JsonReader"/> for this token.
1030
    /// </summary>
1031
    /// <returns>An <see cref="JsonReader"/> that can be used to read this token and its descendants.</returns>
1032
    public JsonReader CreateReader()
1033
    {
1034
 38
      return new JTokenReader(this);
1035
 38
    }
1036

  
1037
    internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer)
1038
    {
1039
 28
      ValidationUtils.ArgumentNotNull(o, "o");
1040
 28
      ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer");
1041

  
1042
      JToken token;
1043
 28
      using (JTokenWriter jsonWriter = new JTokenWriter())
1044
      {
1045
 28
        jsonSerializer.Serialize(jsonWriter, o);
1046
 28
        token = jsonWriter.Token;
1047
      }
1048

  
1049
 28
      return token;
1050
 28
    }
1051

  
1052
    /// <summary>
1053
    /// Creates a <see cref="JToken"/> from an object.
1054
    /// </summary>
1055
    /// <param name="o">The object that will be used to create <see cref="JToken"/>.</param>
1056
    /// <returns>A <see cref="JToken"/> with the value of the specified object</returns>
1057
    public static JToken FromObject(object o)
1058
    {
1059
 18
      return FromObjectInternal(o, new JsonSerializer());
1060
 18
    }
1061

  
1062
    /// <summary>
1063
    /// Creates a <see cref="JToken"/> from an object using the specified <see cref="JsonSerializer"/>.
1064
    /// </summary>
1065
    /// <param name="o">The object that will be used to create <see cref="JToken"/>.</param>
1066
    /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used when reading the object.</param>
1067
    /// <returns>A <see cref="JToken"/> with the value of the specified object</returns>
1068
    public static JToken FromObject(object o, JsonSerializer jsonSerializer)
1069
    {
1070
 0
      return FromObjectInternal(o, jsonSerializer);
1071
 0
    }
1072

  
1073
    /// <summary>
1074
    /// Creates a <see cref="JToken"/> from a <see cref="JsonReader"/>.
1075
    /// </summary>
1076
    /// <param name="reader">An <see cref="JsonReader"/> positioned at the token to read into this <see cref="JToken"/>.</param>
1077
    /// <returns>
1078
    /// An <see cref="JToken"/> that contains the token and its descendant tokens
1079
    /// that were read from the reader. The runtime type of the token is determined
1080
    /// by the token type of the first token encountered in the reader.
1081
    /// </returns>
1082
    public static JToken ReadFrom(JsonReader reader)
1083
    {
1084
 87
      ValidationUtils.ArgumentNotNull(reader, "reader");
1085

  
1086
 87
      if (reader.TokenType == JsonToken.None)
1087
      {
1088
 33
        if (!reader.Read())
1089
 0
          throw new Exception("Error reading JToken from JsonReader.");
1090
      }
1091

  
1092
 87
      if (reader.TokenType == JsonToken.StartObject)
1093
 23
        return JObject.Load(reader);
1094

  
1095
 64
      if (reader.TokenType == JsonToken.StartArray)
1096
 3
        return JArray.Load(reader);
1097

  
1098
 61
      if (reader.TokenType == JsonToken.PropertyName)
1099
 1
        return JProperty.Load(reader);
1100

  
1101
 60
      if (reader.TokenType == JsonToken.StartConstructor)
1102
 1
        return JConstructor.Load(reader);
1103

  
1104
      // hack. change to look at TokenType rather than using value
1105
 59
      if (!JsonReader.IsStartToken(reader.TokenType))
1106
 59
        return new JValue(reader.Value);
1107

  
1108
      // TODO: loading constructor and parameters?
1109
 0
      throw new Exception("Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
1110
 87
    }
1111

  
1112
    internal void SetLineInfo(IJsonLineInfo lineInfo)
1113
    {
1114
 923
      if (lineInfo == null || !lineInfo.HasLineInfo())
1115
 58
        return;
1116

  
1117
 865
      SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
1118
 923
    }
1119

  
1120
    internal void SetLineInfo(int lineNumber, int linePosition)
1121
    {
1122
 865
      _lineNumber = lineNumber;
1123
 865
      _linePosition = linePosition;
1124
 865
    }
1125

  
1126
    bool IJsonLineInfo.HasLineInfo()
1127
    {
1128
 51
      return (_lineNumber != null && _linePosition != null);
1129
 51
    }
1130

  
1131
    int IJsonLineInfo.LineNumber
1132
    {
1133
 46
      get { return _lineNumber ?? 0; }
1134
    }
1135

  
1136
    int IJsonLineInfo.LinePosition
1137
    {
1138
 46
      get { return _linePosition ?? 0; }
1139
    }
1140

  
1141
    /// <summary>
1142
    /// Selects the token that matches the object path.
1143
    /// </summary>
1144
    /// <param name="path">
1145
    /// The object path from the current <see cref="JToken"/> to the <see cref="JToken"/>
1146
    /// to be returned. This must be a string of property names or array indexes separated
1147
    /// by periods, such as <code>Tables[0].DefaultView[0].Price</code> in C# or
1148
    /// <code>Tables(0).DefaultView(0).Price</code> in Visual Basic.
1149
    /// </param>
1150
    /// <returns>The <see cref="JToken"/> that matches the object path or a null reference if no matching token is found.</returns>
1151
    public JToken SelectToken(string path)
1152
    {
1153
 16
      return SelectToken(path, false);
1154
 16
    }
1155

  
1156
    /// <summary>
1157
    /// Selects the token that matches the object path.
1158
    /// </summary>
1159
    /// <param name="path">
1160
    /// The object path from the current <see cref="JToken"/> to the <see cref="JToken"/>
1161
    /// to be returned. This must be a string of property names or array indexes separated
1162
    /// by periods, such as <code>Tables[0].DefaultView[0].Price</code> in C# or
1163
    /// <code>Tables(0).DefaultView(0).Price</code> in Visual Basic.
1164
    /// </param>
1165
    /// <param name="errorWhenNoMatch">A flag to indicate whether an error should be thrown if no token is found.</param>
1166
    /// <returns>The <see cref="JToken"/> that matches the object path.</returns>
1167
    public JToken SelectToken(string path, bool errorWhenNoMatch)
1168
    {
1169
 21
      JPath p = new JPath(path);
1170
 21
      return p.Evaluate(this, errorWhenNoMatch);
1171
 16
    }
1172
  }
1173
}