You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2686 lines
100 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  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. using System;
  26. using System.Collections.Generic;
  27. using Newtonsoft.Json.Linq.JsonPath;
  28. #if !NET20
  29. using System.Dynamic;
  30. using System.Linq.Expressions;
  31. #endif
  32. using System.IO;
  33. #if HAVE_BIG_INTEGER
  34. using System.Numerics;
  35. #endif
  36. using Newtonsoft.Json.Utilities;
  37. using System.Diagnostics;
  38. using System.Globalization;
  39. using System.Collections;
  40. #if NET20
  41. using Newtonsoft.Json.Utilities.LinqBridge;
  42. #else
  43. using System.Linq;
  44. #endif
  45. namespace Newtonsoft.Json.Linq
  46. {
  47. /// <summary>
  48. /// Represents an abstract JSON token.
  49. /// </summary>
  50. internal abstract partial class JToken : IJEnumerable<JToken>, IJsonLineInfo, ICloneable
  51. #if !NET20
  52. , IDynamicMetaObjectProvider
  53. #endif
  54. {
  55. private static JTokenEqualityComparer _equalityComparer;
  56. private JContainer _parent;
  57. private JToken _previous;
  58. private JToken _next;
  59. private object _annotations;
  60. private static readonly JTokenType[] BooleanTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean };
  61. private static readonly JTokenType[] NumberTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean };
  62. #if HAVE_BIG_INTEGER
  63. private static readonly JTokenType[] BigIntegerTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes };
  64. #endif
  65. private static readonly JTokenType[] StringTypes = new[] { JTokenType.Date, JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes, JTokenType.Guid, JTokenType.TimeSpan, JTokenType.Uri };
  66. private static readonly JTokenType[] GuidTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Guid, JTokenType.Bytes };
  67. private static readonly JTokenType[] TimeSpanTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.TimeSpan };
  68. private static readonly JTokenType[] UriTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Uri };
  69. private static readonly JTokenType[] CharTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw };
  70. private static readonly JTokenType[] DateTimeTypes = new[] { JTokenType.Date, JTokenType.String, JTokenType.Comment, JTokenType.Raw };
  71. private static readonly JTokenType[] BytesTypes = new[] { JTokenType.Bytes, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Integer };
  72. /// <summary>
  73. /// Gets a comparer that can compare two tokens for value equality.
  74. /// </summary>
  75. /// <value>A <see cref="JTokenEqualityComparer"/> that can compare two nodes for value equality.</value>
  76. public static JTokenEqualityComparer EqualityComparer
  77. {
  78. get
  79. {
  80. if (_equalityComparer == null)
  81. {
  82. _equalityComparer = new JTokenEqualityComparer();
  83. }
  84. return _equalityComparer;
  85. }
  86. }
  87. /// <summary>
  88. /// Gets or sets the parent.
  89. /// </summary>
  90. /// <value>The parent.</value>
  91. public JContainer Parent
  92. {
  93. [DebuggerStepThrough]
  94. get { return _parent; }
  95. internal set { _parent = value; }
  96. }
  97. /// <summary>
  98. /// Gets the root <see cref="JToken"/> of this <see cref="JToken"/>.
  99. /// </summary>
  100. /// <value>The root <see cref="JToken"/> of this <see cref="JToken"/>.</value>
  101. public JToken Root
  102. {
  103. get
  104. {
  105. JContainer parent = Parent;
  106. if (parent == null)
  107. {
  108. return this;
  109. }
  110. while (parent.Parent != null)
  111. {
  112. parent = parent.Parent;
  113. }
  114. return parent;
  115. }
  116. }
  117. internal abstract JToken CloneToken();
  118. internal abstract bool DeepEquals(JToken node);
  119. /// <summary>
  120. /// Gets the node type for this <see cref="JToken"/>.
  121. /// </summary>
  122. /// <value>The type.</value>
  123. public abstract JTokenType Type { get; }
  124. /// <summary>
  125. /// Gets a value indicating whether this token has child tokens.
  126. /// </summary>
  127. /// <value>
  128. /// <c>true</c> if this token has child values; otherwise, <c>false</c>.
  129. /// </value>
  130. public abstract bool HasValues { get; }
  131. /// <summary>
  132. /// Compares the values of two tokens, including the values of all descendant tokens.
  133. /// </summary>
  134. /// <param name="t1">The first <see cref="JToken"/> to compare.</param>
  135. /// <param name="t2">The second <see cref="JToken"/> to compare.</param>
  136. /// <returns><c>true</c> if the tokens are equal; otherwise <c>false</c>.</returns>
  137. public static bool DeepEquals(JToken t1, JToken t2)
  138. {
  139. return (t1 == t2 || (t1 != null && t2 != null && t1.DeepEquals(t2)));
  140. }
  141. /// <summary>
  142. /// Gets the next sibling token of this node.
  143. /// </summary>
  144. /// <value>The <see cref="JToken"/> that contains the next sibling token.</value>
  145. public JToken Next
  146. {
  147. get => _next;
  148. internal set => _next = value;
  149. }
  150. /// <summary>
  151. /// Gets the previous sibling token of this node.
  152. /// </summary>
  153. /// <value>The <see cref="JToken"/> that contains the previous sibling token.</value>
  154. public JToken Previous
  155. {
  156. get => _previous;
  157. internal set => _previous = value;
  158. }
  159. /// <summary>
  160. /// Gets the path of the JSON token.
  161. /// </summary>
  162. public string Path
  163. {
  164. get
  165. {
  166. if (Parent == null)
  167. {
  168. return string.Empty;
  169. }
  170. List<JsonPosition> positions = new List<JsonPosition>();
  171. JToken previous = null;
  172. for (JToken current = this; current != null; current = current.Parent)
  173. {
  174. switch (current.Type)
  175. {
  176. case JTokenType.Property:
  177. JProperty property = (JProperty)current;
  178. positions.Add(new JsonPosition(JsonContainerType.Object) { PropertyName = property.Name });
  179. break;
  180. case JTokenType.Array:
  181. case JTokenType.Constructor:
  182. if (previous != null)
  183. {
  184. int index = ((IList<JToken>)current).IndexOf(previous);
  185. positions.Add(new JsonPosition(JsonContainerType.Array) { Position = index });
  186. }
  187. break;
  188. }
  189. previous = current;
  190. }
  191. positions.FastReverse();
  192. // positions.Reverse();
  193. return JsonPosition.BuildPath(positions, null);
  194. }
  195. }
  196. internal JToken()
  197. {
  198. }
  199. /// <summary>
  200. /// Adds the specified content immediately after this token.
  201. /// </summary>
  202. /// <param name="content">A content object that contains simple content or a collection of content objects to be added after this token.</param>
  203. public void AddAfterSelf(object content)
  204. {
  205. if (_parent == null)
  206. {
  207. throw new InvalidOperationException("The parent is missing.");
  208. }
  209. int index = _parent.IndexOfItem(this);
  210. _parent.AddInternal(index + 1, content, false);
  211. }
  212. /// <summary>
  213. /// Adds the specified content immediately before this token.
  214. /// </summary>
  215. /// <param name="content">A content object that contains simple content or a collection of content objects to be added before this token.</param>
  216. public void AddBeforeSelf(object content)
  217. {
  218. if (_parent == null)
  219. {
  220. throw new InvalidOperationException("The parent is missing.");
  221. }
  222. int index = _parent.IndexOfItem(this);
  223. _parent.AddInternal(index, content, false);
  224. }
  225. /// <summary>
  226. /// Returns a collection of the ancestor tokens of this token.
  227. /// </summary>
  228. /// <returns>A collection of the ancestor tokens of this token.</returns>
  229. public IEnumerable<JToken> Ancestors()
  230. {
  231. return GetAncestors(false);
  232. }
  233. /// <summary>
  234. /// Returns a collection of tokens that contain this token, and the ancestors of this token.
  235. /// </summary>
  236. /// <returns>A collection of tokens that contain this token, and the ancestors of this token.</returns>
  237. public IEnumerable<JToken> AncestorsAndSelf()
  238. {
  239. return GetAncestors(true);
  240. }
  241. internal IEnumerable<JToken> GetAncestors(bool self)
  242. {
  243. for (JToken current = self ? this : Parent; current != null; current = current.Parent)
  244. {
  245. yield return current;
  246. }
  247. }
  248. /// <summary>
  249. /// Returns a collection of the sibling tokens after this token, in document order.
  250. /// </summary>
  251. /// <returns>A collection of the sibling tokens after this tokens, in document order.</returns>
  252. public IEnumerable<JToken> AfterSelf()
  253. {
  254. if (Parent == null)
  255. {
  256. yield break;
  257. }
  258. for (JToken o = Next; o != null; o = o.Next)
  259. {
  260. yield return o;
  261. }
  262. }
  263. /// <summary>
  264. /// Returns a collection of the sibling tokens before this token, in document order.
  265. /// </summary>
  266. /// <returns>A collection of the sibling tokens before this token, in document order.</returns>
  267. public IEnumerable<JToken> BeforeSelf()
  268. {
  269. for (JToken o = Parent.First; o != this; o = o.Next)
  270. {
  271. yield return o;
  272. }
  273. }
  274. /// <summary>
  275. /// Gets the <see cref="JToken"/> with the specified key.
  276. /// </summary>
  277. /// <value>The <see cref="JToken"/> with the specified key.</value>
  278. public virtual JToken this[object key]
  279. {
  280. get => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
  281. set => throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
  282. }
  283. /// <summary>
  284. /// Gets the <see cref="JToken"/> with the specified key converted to the specified type.
  285. /// </summary>
  286. /// <typeparam name="T">The type to convert the token to.</typeparam>
  287. /// <param name="key">The token key.</param>
  288. /// <returns>The converted token value.</returns>
  289. public virtual T Value<T>(object key)
  290. {
  291. JToken token = this[key];
  292. // null check to fix MonoTouch issue - https://github.com/dolbz/Newtonsoft.Json/commit/a24e3062846b30ee505f3271ac08862bb471b822
  293. return token == null ? default(T) : Extensions.Convert<JToken, T>(token);
  294. }
  295. /// <summary>
  296. /// Get the first child token of this token.
  297. /// </summary>
  298. /// <value>A <see cref="JToken"/> containing the first child token of the <see cref="JToken"/>.</value>
  299. public virtual JToken First => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
  300. /// <summary>
  301. /// Get the last child token of this token.
  302. /// </summary>
  303. /// <value>A <see cref="JToken"/> containing the last child token of the <see cref="JToken"/>.</value>
  304. public virtual JToken Last => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
  305. /// <summary>
  306. /// Returns a collection of the child tokens of this token, in document order.
  307. /// </summary>
  308. /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> containing the child tokens of this <see cref="JToken"/>, in document order.</returns>
  309. public virtual JEnumerable<JToken> Children()
  310. {
  311. return JEnumerable<JToken>.Empty;
  312. }
  313. /// <summary>
  314. /// Returns a collection of the child tokens of this token, in document order, filtered by the specified type.
  315. /// </summary>
  316. /// <typeparam name="T">The type to filter the child tokens on.</typeparam>
  317. /// <returns>A <see cref="JEnumerable{T}"/> containing the child tokens of this <see cref="JToken"/>, in document order.</returns>
  318. public JEnumerable<T> Children<T>() where T : JToken
  319. {
  320. return new JEnumerable<T>(Children().OfType<T>());
  321. }
  322. /// <summary>
  323. /// Returns a collection of the child values of this token, in document order.
  324. /// </summary>
  325. /// <typeparam name="T">The type to convert the values to.</typeparam>
  326. /// <returns>A <see cref="IEnumerable{T}"/> containing the child values of this <see cref="JToken"/>, in document order.</returns>
  327. public virtual IEnumerable<T> Values<T>()
  328. {
  329. throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
  330. }
  331. /// <summary>
  332. /// Removes this token from its parent.
  333. /// </summary>
  334. public void Remove()
  335. {
  336. if (_parent == null)
  337. {
  338. throw new InvalidOperationException("The parent is missing.");
  339. }
  340. _parent.RemoveItem(this);
  341. }
  342. /// <summary>
  343. /// Replaces this token with the specified token.
  344. /// </summary>
  345. /// <param name="value">The value.</param>
  346. public void Replace(JToken value)
  347. {
  348. if (_parent == null)
  349. {
  350. throw new InvalidOperationException("The parent is missing.");
  351. }
  352. _parent.ReplaceItem(this, value);
  353. }
  354. /// <summary>
  355. /// Writes this token to a <see cref="JsonWriter"/>.
  356. /// </summary>
  357. /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
  358. /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
  359. public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters);
  360. /// <summary>
  361. /// Returns the indented JSON for this token.
  362. /// </summary>
  363. /// <returns>
  364. /// The indented JSON for this token.
  365. /// </returns>
  366. public override string ToString()
  367. {
  368. return ToString(Formatting.Indented);
  369. }
  370. /// <summary>
  371. /// Returns the JSON for this token using the given formatting and converters.
  372. /// </summary>
  373. /// <param name="formatting">Indicates how the output should be formatted.</param>
  374. /// <param name="converters">A collection of <see cref="JsonConverter"/>s which will be used when writing the token.</param>
  375. /// <returns>The JSON for this token using the given formatting and converters.</returns>
  376. public string ToString(Formatting formatting, params JsonConverter[] converters)
  377. {
  378. using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
  379. {
  380. JsonTextWriter jw = new JsonTextWriter(sw);
  381. jw.Formatting = formatting;
  382. WriteTo(jw, converters);
  383. return sw.ToString();
  384. }
  385. }
  386. private static JValue EnsureValue(JToken value)
  387. {
  388. if (value == null)
  389. {
  390. throw new ArgumentNullException(nameof(value));
  391. }
  392. if (value is JProperty property)
  393. {
  394. value = property.Value;
  395. }
  396. JValue v = value as JValue;
  397. return v;
  398. }
  399. private static string GetType(JToken token)
  400. {
  401. ValidationUtils.ArgumentNotNull(token, nameof(token));
  402. if (token is JProperty)
  403. {
  404. token = ((JProperty)token).Value;
  405. }
  406. return token.Type.ToString();
  407. }
  408. private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullable)
  409. {
  410. return (Array.IndexOf(validTypes, o.Type) != -1) || (nullable && (o.Type == JTokenType.Null || o.Type == JTokenType.Undefined));
  411. }
  412. #region Cast from operators
  413. /// <summary>
  414. /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Boolean"/>.
  415. /// </summary>
  416. /// <param name="value">The value.</param>
  417. /// <returns>The result of the conversion.</returns>
  418. public static explicit operator bool(JToken value)
  419. {
  420. JValue v = EnsureValue(value);
  421. if (v == null || !ValidateToken(v, BooleanTypes, false))
  422. {
  423. throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  424. }
  425. #if HAVE_BIG_INTEGER
  426. if (v.Value is BigInteger integer)
  427. {
  428. return Convert.ToBoolean((int)integer);
  429. }
  430. #endif
  431. return Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture);
  432. }
  433. #if !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. JValue v = EnsureValue(value);
  442. if (v == null || !ValidateToken(v, DateTimeTypes, false))
  443. {
  444. throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  445. }
  446. if (v.Value is DateTimeOffset offset)
  447. {
  448. return offset;
  449. }
  450. if (v.Value is string s)
  451. {
  452. return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture);
  453. }
  454. return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture));
  455. }
  456. #endif
  457. /// <summary>
  458. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Boolean"/>.
  459. /// </summary>
  460. /// <param name="value">The value.</param>
  461. /// <returns>The result of the conversion.</returns>
  462. public static explicit operator bool?(JToken value)
  463. {
  464. if (value == null)
  465. {
  466. return null;
  467. }
  468. JValue v = EnsureValue(value);
  469. if (v == null || !ValidateToken(v, BooleanTypes, true))
  470. {
  471. throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  472. }
  473. #if HAVE_BIG_INTEGER
  474. if (v.Value is BigInteger integer)
  475. {
  476. return Convert.ToBoolean((int)integer);
  477. }
  478. #endif
  479. return (v.Value != null) ? (bool?)Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture) : null;
  480. }
  481. /// <summary>
  482. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Int64"/>.
  483. /// </summary>
  484. /// <param name="value">The value.</param>
  485. /// <returns>The result of the conversion.</returns>
  486. public static explicit operator long(JToken value)
  487. {
  488. JValue v = EnsureValue(value);
  489. if (v == null || !ValidateToken(v, NumberTypes, false))
  490. {
  491. throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  492. }
  493. #if HAVE_BIG_INTEGER
  494. if (v.Value is BigInteger integer)
  495. {
  496. return (long)integer;
  497. }
  498. #endif
  499. return Convert.ToInt64(v.Value, CultureInfo.InvariantCulture);
  500. }
  501. /// <summary>
  502. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="DateTime"/>.
  503. /// </summary>
  504. /// <param name="value">The value.</param>
  505. /// <returns>The result of the conversion.</returns>
  506. public static explicit operator DateTime?(JToken value)
  507. {
  508. if (value == null)
  509. {
  510. return null;
  511. }
  512. JValue v = EnsureValue(value);
  513. if (v == null || !ValidateToken(v, DateTimeTypes, true))
  514. {
  515. throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  516. }
  517. #if !NET20
  518. if (v.Value is DateTimeOffset offset)
  519. {
  520. return offset.DateTime;
  521. }
  522. #endif
  523. return (v.Value != null) ? (DateTime?)Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture) : null;
  524. }
  525. #if !NET20
  526. /// <summary>
  527. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="DateTimeOffset"/>.
  528. /// </summary>
  529. /// <param name="value">The value.</param>
  530. /// <returns>The result of the conversion.</returns>
  531. public static explicit operator DateTimeOffset?(JToken value)
  532. {
  533. if (value == null)
  534. {
  535. return null;
  536. }
  537. JValue v = EnsureValue(value);
  538. if (v == null || !ValidateToken(v, DateTimeTypes, true))
  539. {
  540. throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  541. }
  542. if (v.Value == null)
  543. {
  544. return null;
  545. }
  546. if (v.Value is DateTimeOffset offset)
  547. {
  548. return offset;
  549. }
  550. if (v.Value is string s)
  551. {
  552. return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture);
  553. }
  554. return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture));
  555. }
  556. #endif
  557. /// <summary>
  558. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Decimal"/>.
  559. /// </summary>
  560. /// <param name="value">The value.</param>
  561. /// <returns>The result of the conversion.</returns>
  562. public static explicit operator decimal?(JToken value)
  563. {
  564. if (value == null)
  565. {
  566. return null;
  567. }
  568. JValue v = EnsureValue(value);
  569. if (v == null || !ValidateToken(v, NumberTypes, true))
  570. {
  571. throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  572. }
  573. #if HAVE_BIG_INTEGER
  574. if (v.Value is BigInteger integer)
  575. {
  576. return (decimal?)integer;
  577. }
  578. #endif
  579. return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null;
  580. }
  581. /// <summary>
  582. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Double"/>.
  583. /// </summary>
  584. /// <param name="value">The value.</param>
  585. /// <returns>The result of the conversion.</returns>
  586. public static explicit operator double?(JToken value)
  587. {
  588. if (value == null)
  589. {
  590. return null;
  591. }
  592. JValue v = EnsureValue(value);
  593. if (v == null || !ValidateToken(v, NumberTypes, true))
  594. {
  595. throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  596. }
  597. #if HAVE_BIG_INTEGER
  598. if (v.Value is BigInteger integer)
  599. {
  600. return (double?)integer;
  601. }
  602. #endif
  603. return (v.Value != null) ? (double?)Convert.ToDouble(v.Value, CultureInfo.InvariantCulture) : null;
  604. }
  605. /// <summary>
  606. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Char"/>.
  607. /// </summary>
  608. /// <param name="value">The value.</param>
  609. /// <returns>The result of the conversion.</returns>
  610. public static explicit operator char?(JToken value)
  611. {
  612. if (value == null)
  613. {
  614. return null;
  615. }
  616. JValue v = EnsureValue(value);
  617. if (v == null || !ValidateToken(v, CharTypes, true))
  618. {
  619. throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  620. }
  621. #if HAVE_BIG_INTEGER
  622. if (v.Value is BigInteger integer)
  623. {
  624. return (char?)integer;
  625. }
  626. #endif
  627. return (v.Value != null) ? (char?)Convert.ToChar(v.Value, CultureInfo.InvariantCulture) : null;
  628. }
  629. /// <summary>
  630. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Int32"/>.
  631. /// </summary>
  632. /// <param name="value">The value.</param>
  633. /// <returns>The result of the conversion.</returns>
  634. public static explicit operator int(JToken value)
  635. {
  636. JValue v = EnsureValue(value);
  637. if (v == null || !ValidateToken(v, NumberTypes, false))
  638. {
  639. throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  640. }
  641. #if HAVE_BIG_INTEGER
  642. if (v.Value is BigInteger integer)
  643. {
  644. return (int)integer;
  645. }
  646. #endif
  647. return Convert.ToInt32(v.Value, CultureInfo.InvariantCulture);
  648. }
  649. /// <summary>
  650. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Int16"/>.
  651. /// </summary>
  652. /// <param name="value">The value.</param>
  653. /// <returns>The result of the conversion.</returns>
  654. public static explicit operator short(JToken value)
  655. {
  656. JValue v = EnsureValue(value);
  657. if (v == null || !ValidateToken(v, NumberTypes, false))
  658. {
  659. throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  660. }
  661. #if HAVE_BIG_INTEGER
  662. if (v.Value is BigInteger integer)
  663. {
  664. return (short)integer;
  665. }
  666. #endif
  667. return Convert.ToInt16(v.Value, CultureInfo.InvariantCulture);
  668. }
  669. /// <summary>
  670. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="UInt16"/>.
  671. /// </summary>
  672. /// <param name="value">The value.</param>
  673. /// <returns>The result of the conversion.</returns>
  674. public static explicit operator ushort(JToken value)
  675. {
  676. JValue v = EnsureValue(value);
  677. if (v == null || !ValidateToken(v, NumberTypes, false))
  678. {
  679. throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  680. }
  681. #if HAVE_BIG_INTEGER
  682. if (v.Value is BigInteger integer)
  683. {
  684. return (ushort)integer;
  685. }
  686. #endif
  687. return Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture);
  688. }
  689. /// <summary>
  690. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Char"/>.
  691. /// </summary>
  692. /// <param name="value">The value.</param>
  693. /// <returns>The result of the conversion.</returns>
  694. public static explicit operator char(JToken value)
  695. {
  696. JValue v = EnsureValue(value);
  697. if (v == null || !ValidateToken(v, CharTypes, false))
  698. {
  699. throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  700. }
  701. #if HAVE_BIG_INTEGER
  702. if (v.Value is BigInteger integer)
  703. {
  704. return (char)integer;
  705. }
  706. #endif
  707. return Convert.ToChar(v.Value, CultureInfo.InvariantCulture);
  708. }
  709. /// <summary>
  710. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Byte"/>.
  711. /// </summary>
  712. /// <param name="value">The value.</param>
  713. /// <returns>The result of the conversion.</returns>
  714. public static explicit operator byte(JToken value)
  715. {
  716. JValue v = EnsureValue(value);
  717. if (v == null || !ValidateToken(v, NumberTypes, false))
  718. {
  719. throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  720. }
  721. #if HAVE_BIG_INTEGER
  722. if (v.Value is BigInteger integer)
  723. {
  724. return (byte)integer;
  725. }
  726. #endif
  727. return Convert.ToByte(v.Value, CultureInfo.InvariantCulture);
  728. }
  729. /// <summary>
  730. /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.SByte"/>.
  731. /// </summary>
  732. /// <param name="value">The value.</param>
  733. /// <returns>The result of the conversion.</returns>
  734. public static explicit operator sbyte(JToken value)
  735. {
  736. JValue v = EnsureValue(value);
  737. if (v == null || !ValidateToken(v, NumberTypes, false))
  738. {
  739. throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  740. }
  741. #if HAVE_BIG_INTEGER
  742. if (v.Value is BigInteger integer)
  743. {
  744. return (sbyte)integer;
  745. }
  746. #endif
  747. return Convert.ToSByte(v.Value, CultureInfo.InvariantCulture);
  748. }
  749. /// <summary>
  750. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Int32"/> .
  751. /// </summary>
  752. /// <param name="value">The value.</param>
  753. /// <returns>The result of the conversion.</returns>
  754. public static explicit operator int?(JToken value)
  755. {
  756. if (value == null)
  757. {
  758. return null;
  759. }
  760. JValue v = EnsureValue(value);
  761. if (v == null || !ValidateToken(v, NumberTypes, true))
  762. {
  763. throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  764. }
  765. #if HAVE_BIG_INTEGER
  766. if (v.Value is BigInteger integer)
  767. {
  768. return (int?)integer;
  769. }
  770. #endif
  771. return (v.Value != null) ? (int?)Convert.ToInt32(v.Value, CultureInfo.InvariantCulture) : null;
  772. }
  773. /// <summary>
  774. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Int16"/>.
  775. /// </summary>
  776. /// <param name="value">The value.</param>
  777. /// <returns>The result of the conversion.</returns>
  778. public static explicit operator short?(JToken value)
  779. {
  780. if (value == null)
  781. {
  782. return null;
  783. }
  784. JValue v = EnsureValue(value);
  785. if (v == null || !ValidateToken(v, NumberTypes, true))
  786. {
  787. throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  788. }
  789. #if HAVE_BIG_INTEGER
  790. if (v.Value is BigInteger integer)
  791. {
  792. return (short?)integer;
  793. }
  794. #endif
  795. return (v.Value != null) ? (short?)Convert.ToInt16(v.Value, CultureInfo.InvariantCulture) : null;
  796. }
  797. /// <summary>
  798. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="UInt16"/>.
  799. /// </summary>
  800. /// <param name="value">The value.</param>
  801. /// <returns>The result of the conversion.</returns>
  802. public static explicit operator ushort?(JToken value)
  803. {
  804. if (value == null)
  805. {
  806. return null;
  807. }
  808. JValue v = EnsureValue(value);
  809. if (v == null || !ValidateToken(v, NumberTypes, true))
  810. {
  811. throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  812. }
  813. #if HAVE_BIG_INTEGER
  814. if (v.Value is BigInteger integer)
  815. {
  816. return (ushort?)integer;
  817. }
  818. #endif
  819. return (v.Value != null) ? (ushort?)Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture) : null;
  820. }
  821. /// <summary>
  822. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Byte"/>.
  823. /// </summary>
  824. /// <param name="value">The value.</param>
  825. /// <returns>The result of the conversion.</returns>
  826. public static explicit operator byte?(JToken value)
  827. {
  828. if (value == null)
  829. {
  830. return null;
  831. }
  832. JValue v = EnsureValue(value);
  833. if (v == null || !ValidateToken(v, NumberTypes, true))
  834. {
  835. throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  836. }
  837. #if HAVE_BIG_INTEGER
  838. if (v.Value is BigInteger integer)
  839. {
  840. return (byte?)integer;
  841. }
  842. #endif
  843. return (v.Value != null) ? (byte?)Convert.ToByte(v.Value, CultureInfo.InvariantCulture) : null;
  844. }
  845. /// <summary>
  846. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="SByte"/>.
  847. /// </summary>
  848. /// <param name="value">The value.</param>
  849. /// <returns>The result of the conversion.</returns>
  850. public static explicit operator sbyte?(JToken value)
  851. {
  852. if (value == null)
  853. {
  854. return null;
  855. }
  856. JValue v = EnsureValue(value);
  857. if (v == null || !ValidateToken(v, NumberTypes, true))
  858. {
  859. throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  860. }
  861. #if HAVE_BIG_INTEGER
  862. if (v.Value is BigInteger integer)
  863. {
  864. return (sbyte?)integer;
  865. }
  866. #endif
  867. return (v.Value != null) ? (sbyte?)Convert.ToSByte(v.Value, CultureInfo.InvariantCulture) : null;
  868. }
  869. /// <summary>
  870. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="DateTime"/>.
  871. /// </summary>
  872. /// <param name="value">The value.</param>
  873. /// <returns>The result of the conversion.</returns>
  874. public static explicit operator DateTime(JToken value)
  875. {
  876. JValue v = EnsureValue(value);
  877. if (v == null || !ValidateToken(v, DateTimeTypes, false))
  878. {
  879. throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  880. }
  881. #if !NET20
  882. if (v.Value is DateTimeOffset offset)
  883. {
  884. return offset.DateTime;
  885. }
  886. #endif
  887. return Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture);
  888. }
  889. /// <summary>
  890. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Int64"/>.
  891. /// </summary>
  892. /// <param name="value">The value.</param>
  893. /// <returns>The result of the conversion.</returns>
  894. public static explicit operator long?(JToken value)
  895. {
  896. if (value == null)
  897. {
  898. return null;
  899. }
  900. JValue v = EnsureValue(value);
  901. if (v == null || !ValidateToken(v, NumberTypes, true))
  902. {
  903. throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  904. }
  905. #if HAVE_BIG_INTEGER
  906. if (v.Value is BigInteger integer)
  907. {
  908. return (long?)integer;
  909. }
  910. #endif
  911. return (v.Value != null) ? (long?)Convert.ToInt64(v.Value, CultureInfo.InvariantCulture) : null;
  912. }
  913. /// <summary>
  914. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Single"/>.
  915. /// </summary>
  916. /// <param name="value">The value.</param>
  917. /// <returns>The result of the conversion.</returns>
  918. public static explicit operator float?(JToken value)
  919. {
  920. if (value == null)
  921. {
  922. return null;
  923. }
  924. JValue v = EnsureValue(value);
  925. if (v == null || !ValidateToken(v, NumberTypes, true))
  926. {
  927. throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  928. }
  929. #if HAVE_BIG_INTEGER
  930. if (v.Value is BigInteger integer)
  931. {
  932. return (float?)integer;
  933. }
  934. #endif
  935. return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null;
  936. }
  937. /// <summary>
  938. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Decimal"/>.
  939. /// </summary>
  940. /// <param name="value">The value.</param>
  941. /// <returns>The result of the conversion.</returns>
  942. public static explicit operator decimal(JToken value)
  943. {
  944. JValue v = EnsureValue(value);
  945. if (v == null || !ValidateToken(v, NumberTypes, false))
  946. {
  947. throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  948. }
  949. #if HAVE_BIG_INTEGER
  950. if (v.Value is BigInteger integer)
  951. {
  952. return (decimal)integer;
  953. }
  954. #endif
  955. return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture);
  956. }
  957. /// <summary>
  958. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="UInt32"/>.
  959. /// </summary>
  960. /// <param name="value">The value.</param>
  961. /// <returns>The result of the conversion.</returns>
  962. public static explicit operator uint?(JToken value)
  963. {
  964. if (value == null)
  965. {
  966. return null;
  967. }
  968. JValue v = EnsureValue(value);
  969. if (v == null || !ValidateToken(v, NumberTypes, true))
  970. {
  971. throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  972. }
  973. #if HAVE_BIG_INTEGER
  974. if (v.Value is BigInteger integer)
  975. {
  976. return (uint?)integer;
  977. }
  978. #endif
  979. return (v.Value != null) ? (uint?)Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture) : null;
  980. }
  981. /// <summary>
  982. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="UInt64"/>.
  983. /// </summary>
  984. /// <param name="value">The value.</param>
  985. /// <returns>The result of the conversion.</returns>
  986. public static explicit operator ulong?(JToken value)
  987. {
  988. if (value == null)
  989. {
  990. return null;
  991. }
  992. JValue v = EnsureValue(value);
  993. if (v == null || !ValidateToken(v, NumberTypes, true))
  994. {
  995. throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  996. }
  997. #if HAVE_BIG_INTEGER
  998. if (v.Value is BigInteger integer)
  999. {
  1000. return (ulong?)integer;
  1001. }
  1002. #endif
  1003. return (v.Value != null) ? (ulong?)Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture) : null;
  1004. }
  1005. /// <summary>
  1006. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Double"/>.
  1007. /// </summary>
  1008. /// <param name="value">The value.</param>
  1009. /// <returns>The result of the conversion.</returns>
  1010. public static explicit operator double(JToken value)
  1011. {
  1012. JValue v = EnsureValue(value);
  1013. if (v == null || !ValidateToken(v, NumberTypes, false))
  1014. {
  1015. throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1016. }
  1017. #if HAVE_BIG_INTEGER
  1018. if (v.Value is BigInteger integer)
  1019. {
  1020. return (double)integer;
  1021. }
  1022. #endif
  1023. return Convert.ToDouble(v.Value, CultureInfo.InvariantCulture);
  1024. }
  1025. /// <summary>
  1026. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Single"/>.
  1027. /// </summary>
  1028. /// <param name="value">The value.</param>
  1029. /// <returns>The result of the conversion.</returns>
  1030. public static explicit operator float(JToken value)
  1031. {
  1032. JValue v = EnsureValue(value);
  1033. if (v == null || !ValidateToken(v, NumberTypes, false))
  1034. {
  1035. throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1036. }
  1037. #if HAVE_BIG_INTEGER
  1038. if (v.Value is BigInteger integer)
  1039. {
  1040. return (float)integer;
  1041. }
  1042. #endif
  1043. return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture);
  1044. }
  1045. /// <summary>
  1046. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="String"/>.
  1047. /// </summary>
  1048. /// <param name="value">The value.</param>
  1049. /// <returns>The result of the conversion.</returns>
  1050. public static explicit operator string(JToken value)
  1051. {
  1052. if (value == null)
  1053. {
  1054. return null;
  1055. }
  1056. JValue v = EnsureValue(value);
  1057. if (v == null || !ValidateToken(v, StringTypes, true))
  1058. {
  1059. throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1060. }
  1061. if (v.Value == null)
  1062. {
  1063. return null;
  1064. }
  1065. if (v.Value is byte[] bytes)
  1066. {
  1067. return Convert.ToBase64String(bytes);
  1068. }
  1069. #if HAVE_BIG_INTEGER
  1070. if (v.Value is BigInteger integer)
  1071. {
  1072. return integer.ToString(CultureInfo.InvariantCulture);
  1073. }
  1074. #endif
  1075. return Convert.ToString(v.Value, CultureInfo.InvariantCulture);
  1076. }
  1077. /// <summary>
  1078. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="UInt32"/>.
  1079. /// </summary>
  1080. /// <param name="value">The value.</param>
  1081. /// <returns>The result of the conversion.</returns>
  1082. public static explicit operator uint(JToken value)
  1083. {
  1084. JValue v = EnsureValue(value);
  1085. if (v == null || !ValidateToken(v, NumberTypes, false))
  1086. {
  1087. throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1088. }
  1089. #if HAVE_BIG_INTEGER
  1090. if (v.Value is BigInteger integer)
  1091. {
  1092. return (uint)integer;
  1093. }
  1094. #endif
  1095. return Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture);
  1096. }
  1097. /// <summary>
  1098. /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.UInt64"/>.
  1099. /// </summary>
  1100. /// <param name="value">The value.</param>
  1101. /// <returns>The result of the conversion.</returns>
  1102. public static explicit operator ulong(JToken value)
  1103. {
  1104. JValue v = EnsureValue(value);
  1105. if (v == null || !ValidateToken(v, NumberTypes, false))
  1106. {
  1107. throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1108. }
  1109. #if HAVE_BIG_INTEGER
  1110. if (v.Value is BigInteger integer)
  1111. {
  1112. return (ulong)integer;
  1113. }
  1114. #endif
  1115. return Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture);
  1116. }
  1117. /// <summary>
  1118. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Byte"/>[].
  1119. /// </summary>
  1120. /// <param name="value">The value.</param>
  1121. /// <returns>The result of the conversion.</returns>
  1122. public static explicit operator byte[](JToken value)
  1123. {
  1124. if (value == null)
  1125. {
  1126. return null;
  1127. }
  1128. JValue v = EnsureValue(value);
  1129. if (v == null || !ValidateToken(v, BytesTypes, false))
  1130. {
  1131. throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1132. }
  1133. if (v.Value is string)
  1134. {
  1135. return Convert.FromBase64String(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
  1136. }
  1137. #if HAVE_BIG_INTEGER
  1138. if (v.Value is BigInteger integer)
  1139. {
  1140. return integer.ToByteArray();
  1141. }
  1142. #endif
  1143. if (v.Value is byte[] bytes)
  1144. {
  1145. return bytes;
  1146. }
  1147. throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1148. }
  1149. /// <summary>
  1150. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Guid"/>.
  1151. /// </summary>
  1152. /// <param name="value">The value.</param>
  1153. /// <returns>The result of the conversion.</returns>
  1154. public static explicit operator Guid(JToken value)
  1155. {
  1156. JValue v = EnsureValue(value);
  1157. if (v == null || !ValidateToken(v, GuidTypes, false))
  1158. {
  1159. throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1160. }
  1161. if (v.Value is byte[] bytes)
  1162. {
  1163. return new Guid(bytes);
  1164. }
  1165. return (v.Value is Guid guid) ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
  1166. }
  1167. /// <summary>
  1168. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Guid"/> .
  1169. /// </summary>
  1170. /// <param name="value">The value.</param>
  1171. /// <returns>The result of the conversion.</returns>
  1172. public static explicit operator Guid?(JToken value)
  1173. {
  1174. if (value == null)
  1175. {
  1176. return null;
  1177. }
  1178. JValue v = EnsureValue(value);
  1179. if (v == null || !ValidateToken(v, GuidTypes, true))
  1180. {
  1181. throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1182. }
  1183. if (v.Value == null)
  1184. {
  1185. return null;
  1186. }
  1187. if (v.Value is byte[] bytes)
  1188. {
  1189. return new Guid(bytes);
  1190. }
  1191. return (v.Value is Guid guid) ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
  1192. }
  1193. /// <summary>
  1194. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="TimeSpan"/>.
  1195. /// </summary>
  1196. /// <param name="value">The value.</param>
  1197. /// <returns>The result of the conversion.</returns>
  1198. public static explicit operator TimeSpan(JToken value)
  1199. {
  1200. JValue v = EnsureValue(value);
  1201. if (v == null || !ValidateToken(v, TimeSpanTypes, false))
  1202. {
  1203. throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1204. }
  1205. return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
  1206. }
  1207. /// <summary>
  1208. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="TimeSpan"/>.
  1209. /// </summary>
  1210. /// <param name="value">The value.</param>
  1211. /// <returns>The result of the conversion.</returns>
  1212. public static explicit operator TimeSpan?(JToken value)
  1213. {
  1214. if (value == null)
  1215. {
  1216. return null;
  1217. }
  1218. JValue v = EnsureValue(value);
  1219. if (v == null || !ValidateToken(v, TimeSpanTypes, true))
  1220. {
  1221. throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1222. }
  1223. if (v.Value == null)
  1224. {
  1225. return null;
  1226. }
  1227. return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
  1228. }
  1229. /// <summary>
  1230. /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Uri"/>.
  1231. /// </summary>
  1232. /// <param name="value">The value.</param>
  1233. /// <returns>The result of the conversion.</returns>
  1234. public static explicit operator Uri(JToken value)
  1235. {
  1236. if (value == null)
  1237. {
  1238. return null;
  1239. }
  1240. JValue v = EnsureValue(value);
  1241. if (v == null || !ValidateToken(v, UriTypes, true))
  1242. {
  1243. throw new ArgumentException("Can not convert {0} to Uri.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1244. }
  1245. if (v.Value == null)
  1246. {
  1247. return null;
  1248. }
  1249. return (v.Value is Uri uri) ? uri : new Uri(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
  1250. }
  1251. #if HAVE_BIG_INTEGER
  1252. private static BigInteger ToBigInteger(JToken value)
  1253. {
  1254. JValue v = EnsureValue(value);
  1255. if (v == null || !ValidateToken(v, BigIntegerTypes, false))
  1256. {
  1257. throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1258. }
  1259. return ConvertUtils.ToBigInteger(v.Value);
  1260. }
  1261. private static BigInteger? ToBigIntegerNullable(JToken value)
  1262. {
  1263. JValue v = EnsureValue(value);
  1264. if (v == null || !ValidateToken(v, BigIntegerTypes, true))
  1265. {
  1266. throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
  1267. }
  1268. if (v.Value == null)
  1269. {
  1270. return null;
  1271. }
  1272. return ConvertUtils.ToBigInteger(v.Value);
  1273. }
  1274. #endif
  1275. #endregion
  1276. #region Cast to operators
  1277. /// <summary>
  1278. /// Performs an implicit conversion from <see cref="Boolean"/> to <see cref="JToken"/>.
  1279. /// </summary>
  1280. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1281. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1282. public static implicit operator JToken(bool value)
  1283. {
  1284. return new JValue(value);
  1285. }
  1286. #if !NET20
  1287. /// <summary>
  1288. /// Performs an implicit conversion from <see cref="DateTimeOffset"/> to <see cref="JToken"/>.
  1289. /// </summary>
  1290. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1291. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1292. public static implicit operator JToken(DateTimeOffset value)
  1293. {
  1294. return new JValue(value);
  1295. }
  1296. #endif
  1297. /// <summary>
  1298. /// Performs an implicit conversion from <see cref="Byte"/> to <see cref="JToken"/>.
  1299. /// </summary>
  1300. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1301. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1302. public static implicit operator JToken(byte value)
  1303. {
  1304. return new JValue(value);
  1305. }
  1306. /// <summary>
  1307. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Byte"/> to <see cref="JToken"/>.
  1308. /// </summary>
  1309. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1310. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1311. public static implicit operator JToken(byte? value)
  1312. {
  1313. return new JValue(value);
  1314. }
  1315. /// <summary>
  1316. /// Performs an implicit conversion from <see cref="SByte"/> to <see cref="JToken"/>.
  1317. /// </summary>
  1318. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1319. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1320. public static implicit operator JToken(sbyte value)
  1321. {
  1322. return new JValue(value);
  1323. }
  1324. /// <summary>
  1325. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="SByte"/> to <see cref="JToken"/>.
  1326. /// </summary>
  1327. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1328. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1329. public static implicit operator JToken(sbyte? value)
  1330. {
  1331. return new JValue(value);
  1332. }
  1333. /// <summary>
  1334. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Boolean"/> to <see cref="JToken"/>.
  1335. /// </summary>
  1336. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1337. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1338. public static implicit operator JToken(bool? value)
  1339. {
  1340. return new JValue(value);
  1341. }
  1342. /// <summary>
  1343. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Int64"/> to <see cref="JToken"/>.
  1344. /// </summary>
  1345. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1346. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1347. public static implicit operator JToken(long value)
  1348. {
  1349. return new JValue(value);
  1350. }
  1351. /// <summary>
  1352. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="DateTime"/> to <see cref="JToken"/>.
  1353. /// </summary>
  1354. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1355. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1356. public static implicit operator JToken(DateTime? value)
  1357. {
  1358. return new JValue(value);
  1359. }
  1360. #if !NET20
  1361. /// <summary>
  1362. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="DateTimeOffset"/> to <see cref="JToken"/>.
  1363. /// </summary>
  1364. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1365. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1366. public static implicit operator JToken(DateTimeOffset? value)
  1367. {
  1368. return new JValue(value);
  1369. }
  1370. #endif
  1371. /// <summary>
  1372. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Decimal"/> to <see cref="JToken"/>.
  1373. /// </summary>
  1374. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1375. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1376. public static implicit operator JToken(decimal? value)
  1377. {
  1378. return new JValue(value);
  1379. }
  1380. /// <summary>
  1381. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Double"/> to <see cref="JToken"/>.
  1382. /// </summary>
  1383. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1384. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1385. public static implicit operator JToken(double? value)
  1386. {
  1387. return new JValue(value);
  1388. }
  1389. /// <summary>
  1390. /// Performs an implicit conversion from <see cref="Int16"/> to <see cref="JToken"/>.
  1391. /// </summary>
  1392. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1393. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1394. public static implicit operator JToken(short value)
  1395. {
  1396. return new JValue(value);
  1397. }
  1398. /// <summary>
  1399. /// Performs an implicit conversion from <see cref="UInt16"/> to <see cref="JToken"/>.
  1400. /// </summary>
  1401. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1402. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1403. public static implicit operator JToken(ushort value)
  1404. {
  1405. return new JValue(value);
  1406. }
  1407. /// <summary>
  1408. /// Performs an implicit conversion from <see cref="Int32"/> to <see cref="JToken"/>.
  1409. /// </summary>
  1410. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1411. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1412. public static implicit operator JToken(int value)
  1413. {
  1414. return new JValue(value);
  1415. }
  1416. /// <summary>
  1417. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Int32"/> to <see cref="JToken"/>.
  1418. /// </summary>
  1419. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1420. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1421. public static implicit operator JToken(int? value)
  1422. {
  1423. return new JValue(value);
  1424. }
  1425. /// <summary>
  1426. /// Performs an implicit conversion from <see cref="DateTime"/> to <see cref="JToken"/>.
  1427. /// </summary>
  1428. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1429. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1430. public static implicit operator JToken(DateTime value)
  1431. {
  1432. return new JValue(value);
  1433. }
  1434. /// <summary>
  1435. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Int64"/> to <see cref="JToken"/>.
  1436. /// </summary>
  1437. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1438. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1439. public static implicit operator JToken(long? value)
  1440. {
  1441. return new JValue(value);
  1442. }
  1443. /// <summary>
  1444. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Single"/> to <see cref="JToken"/>.
  1445. /// </summary>
  1446. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1447. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1448. public static implicit operator JToken(float? value)
  1449. {
  1450. return new JValue(value);
  1451. }
  1452. /// <summary>
  1453. /// Performs an implicit conversion from <see cref="Decimal"/> to <see cref="JToken"/>.
  1454. /// </summary>
  1455. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1456. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1457. public static implicit operator JToken(decimal value)
  1458. {
  1459. return new JValue(value);
  1460. }
  1461. /// <summary>
  1462. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Int16"/> to <see cref="JToken"/>.
  1463. /// </summary>
  1464. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1465. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1466. public static implicit operator JToken(short? value)
  1467. {
  1468. return new JValue(value);
  1469. }
  1470. /// <summary>
  1471. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="UInt16"/> to <see cref="JToken"/>.
  1472. /// </summary>
  1473. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1474. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1475. public static implicit operator JToken(ushort? value)
  1476. {
  1477. return new JValue(value);
  1478. }
  1479. /// <summary>
  1480. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="UInt32"/> to <see cref="JToken"/>.
  1481. /// </summary>
  1482. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1483. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1484. public static implicit operator JToken(uint? value)
  1485. {
  1486. return new JValue(value);
  1487. }
  1488. /// <summary>
  1489. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="UInt64"/> to <see cref="JToken"/>.
  1490. /// </summary>
  1491. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1492. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1493. public static implicit operator JToken(ulong? value)
  1494. {
  1495. return new JValue(value);
  1496. }
  1497. /// <summary>
  1498. /// Performs an implicit conversion from <see cref="Double"/> to <see cref="JToken"/>.
  1499. /// </summary>
  1500. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1501. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1502. public static implicit operator JToken(double value)
  1503. {
  1504. return new JValue(value);
  1505. }
  1506. /// <summary>
  1507. /// Performs an implicit conversion from <see cref="Single"/> to <see cref="JToken"/>.
  1508. /// </summary>
  1509. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1510. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1511. public static implicit operator JToken(float value)
  1512. {
  1513. return new JValue(value);
  1514. }
  1515. /// <summary>
  1516. /// Performs an implicit conversion from <see cref="String"/> to <see cref="JToken"/>.
  1517. /// </summary>
  1518. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1519. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1520. public static implicit operator JToken(string value)
  1521. {
  1522. return new JValue(value);
  1523. }
  1524. /// <summary>
  1525. /// Performs an implicit conversion from <see cref="UInt32"/> to <see cref="JToken"/>.
  1526. /// </summary>
  1527. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1528. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1529. public static implicit operator JToken(uint value)
  1530. {
  1531. return new JValue(value);
  1532. }
  1533. /// <summary>
  1534. /// Performs an implicit conversion from <see cref="UInt64"/> to <see cref="JToken"/>.
  1535. /// </summary>
  1536. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1537. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1538. public static implicit operator JToken(ulong value)
  1539. {
  1540. return new JValue(value);
  1541. }
  1542. /// <summary>
  1543. /// Performs an implicit conversion from <see cref="Byte"/>[] to <see cref="JToken"/>.
  1544. /// </summary>
  1545. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1546. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1547. public static implicit operator JToken(byte[] value)
  1548. {
  1549. return new JValue(value);
  1550. }
  1551. /// <summary>
  1552. /// Performs an implicit conversion from <see cref="Uri"/> to <see cref="JToken"/>.
  1553. /// </summary>
  1554. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1555. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1556. public static implicit operator JToken(Uri value)
  1557. {
  1558. return new JValue(value);
  1559. }
  1560. /// <summary>
  1561. /// Performs an implicit conversion from <see cref="TimeSpan"/> to <see cref="JToken"/>.
  1562. /// </summary>
  1563. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1564. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1565. public static implicit operator JToken(TimeSpan value)
  1566. {
  1567. return new JValue(value);
  1568. }
  1569. /// <summary>
  1570. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="TimeSpan"/> to <see cref="JToken"/>.
  1571. /// </summary>
  1572. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1573. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1574. public static implicit operator JToken(TimeSpan? value)
  1575. {
  1576. return new JValue(value);
  1577. }
  1578. /// <summary>
  1579. /// Performs an implicit conversion from <see cref="Guid"/> to <see cref="JToken"/>.
  1580. /// </summary>
  1581. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1582. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1583. public static implicit operator JToken(Guid value)
  1584. {
  1585. return new JValue(value);
  1586. }
  1587. /// <summary>
  1588. /// Performs an implicit conversion from <see cref="Nullable{T}"/> of <see cref="Guid"/> to <see cref="JToken"/>.
  1589. /// </summary>
  1590. /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
  1591. /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
  1592. public static implicit operator JToken(Guid? value)
  1593. {
  1594. return new JValue(value);
  1595. }
  1596. #endregion
  1597. IEnumerator IEnumerable.GetEnumerator()
  1598. {
  1599. return ((IEnumerable<JToken>)this).GetEnumerator();
  1600. }
  1601. IEnumerator<JToken> IEnumerable<JToken>.GetEnumerator()
  1602. {
  1603. return Children().GetEnumerator();
  1604. }
  1605. internal abstract int GetDeepHashCode();
  1606. IJEnumerable<JToken> IJEnumerable<JToken>.this[object key] => this[key];
  1607. /// <summary>
  1608. /// Creates a <see cref="JsonReader"/> for this token.
  1609. /// </summary>
  1610. /// <returns>A <see cref="JsonReader"/> that can be used to read this token and its descendants.</returns>
  1611. public JsonReader CreateReader()
  1612. {
  1613. return new JTokenReader(this);
  1614. }
  1615. internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer)
  1616. {
  1617. ValidationUtils.ArgumentNotNull(o, nameof(o));
  1618. ValidationUtils.ArgumentNotNull(jsonSerializer, nameof(jsonSerializer));
  1619. JToken token;
  1620. using (JTokenWriter jsonWriter = new JTokenWriter())
  1621. {
  1622. jsonSerializer.Serialize(jsonWriter, o);
  1623. token = jsonWriter.Token;
  1624. }
  1625. return token;
  1626. }
  1627. /// <summary>
  1628. /// Creates a <see cref="JToken"/> from an object.
  1629. /// </summary>
  1630. /// <param name="o">The object that will be used to create <see cref="JToken"/>.</param>
  1631. /// <returns>A <see cref="JToken"/> with the value of the specified object.</returns>
  1632. public static JToken FromObject(object o)
  1633. {
  1634. return FromObjectInternal(o, JsonSerializer.CreateDefault());
  1635. }
  1636. /// <summary>
  1637. /// Creates a <see cref="JToken"/> from an object using the specified <see cref="JsonSerializer"/>.
  1638. /// </summary>
  1639. /// <param name="o">The object that will be used to create <see cref="JToken"/>.</param>
  1640. /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used when reading the object.</param>
  1641. /// <returns>A <see cref="JToken"/> with the value of the specified object.</returns>
  1642. public static JToken FromObject(object o, JsonSerializer jsonSerializer)
  1643. {
  1644. return FromObjectInternal(o, jsonSerializer);
  1645. }
  1646. /// <summary>
  1647. /// Creates an instance of the specified .NET type from the <see cref="JToken"/>.
  1648. /// </summary>
  1649. /// <typeparam name="T">The object type that the token will be deserialized to.</typeparam>
  1650. /// <returns>The new object created from the JSON value.</returns>
  1651. public T ToObject<T>()
  1652. {
  1653. return (T)ToObject(typeof(T));
  1654. }
  1655. /// <summary>
  1656. /// Creates an instance of the specified .NET type from the <see cref="JToken"/>.
  1657. /// </summary>
  1658. /// <param name="objectType">The object type that the token will be deserialized to.</param>
  1659. /// <returns>The new object created from the JSON value.</returns>
  1660. public object ToObject(Type objectType)
  1661. {
  1662. if (JsonConvert.DefaultSettings == null)
  1663. {
  1664. PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(objectType, out bool isEnum);
  1665. if (isEnum)
  1666. {
  1667. if (Type == JTokenType.String)
  1668. {
  1669. try
  1670. {
  1671. // use serializer so JsonConverter(typeof(StringEnumConverter)) + EnumMemberAttributes are respected
  1672. return ToObject(objectType, JsonSerializer.CreateDefault());
  1673. }
  1674. catch (Exception ex)
  1675. {
  1676. Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType);
  1677. throw new ArgumentException("Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string)this, enumType.Name), ex);
  1678. }
  1679. }
  1680. if (Type == JTokenType.Integer)
  1681. {
  1682. Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType);
  1683. return Enum.ToObject(enumType, ((JValue)this).Value);
  1684. }
  1685. }
  1686. switch (typeCode)
  1687. {
  1688. case PrimitiveTypeCode.BooleanNullable:
  1689. return (bool?)this;
  1690. case PrimitiveTypeCode.Boolean:
  1691. return (bool)this;
  1692. case PrimitiveTypeCode.CharNullable:
  1693. return (char?)this;
  1694. case PrimitiveTypeCode.Char:
  1695. return (char)this;
  1696. case PrimitiveTypeCode.SByte:
  1697. return (sbyte)this;
  1698. case PrimitiveTypeCode.SByteNullable:
  1699. return (sbyte?)this;
  1700. case PrimitiveTypeCode.ByteNullable:
  1701. return (byte?)this;
  1702. case PrimitiveTypeCode.Byte:
  1703. return (byte)this;
  1704. case PrimitiveTypeCode.Int16Nullable:
  1705. return (short?)this;
  1706. case PrimitiveTypeCode.Int16:
  1707. return (short)this;
  1708. case PrimitiveTypeCode.UInt16Nullable:
  1709. return (ushort?)this;
  1710. case PrimitiveTypeCode.UInt16:
  1711. return (ushort)this;
  1712. case PrimitiveTypeCode.Int32Nullable:
  1713. return (int?)this;
  1714. case PrimitiveTypeCode.Int32:
  1715. return (int)this;
  1716. case PrimitiveTypeCode.UInt32Nullable:
  1717. return (uint?)this;
  1718. case PrimitiveTypeCode.UInt32:
  1719. return (uint)this;
  1720. case PrimitiveTypeCode.Int64Nullable:
  1721. return (long?)this;
  1722. case PrimitiveTypeCode.Int64:
  1723. return (long)this;
  1724. case PrimitiveTypeCode.UInt64Nullable:
  1725. return (ulong?)this;
  1726. case PrimitiveTypeCode.UInt64:
  1727. return (ulong)this;
  1728. case PrimitiveTypeCode.SingleNullable:
  1729. return (float?)this;
  1730. case PrimitiveTypeCode.Single:
  1731. return (float)this;
  1732. case PrimitiveTypeCode.DoubleNullable:
  1733. return (double?)this;
  1734. case PrimitiveTypeCode.Double:
  1735. return (double)this;
  1736. case PrimitiveTypeCode.DecimalNullable:
  1737. return (decimal?)this;
  1738. case PrimitiveTypeCode.Decimal:
  1739. return (decimal)this;
  1740. case PrimitiveTypeCode.DateTimeNullable:
  1741. return (DateTime?)this;
  1742. case PrimitiveTypeCode.DateTime:
  1743. return (DateTime)this;
  1744. #if !NET20
  1745. case PrimitiveTypeCode.DateTimeOffsetNullable:
  1746. return (DateTimeOffset?)this;
  1747. case PrimitiveTypeCode.DateTimeOffset:
  1748. return (DateTimeOffset)this;
  1749. #endif
  1750. case PrimitiveTypeCode.String:
  1751. return (string)this;
  1752. case PrimitiveTypeCode.GuidNullable:
  1753. return (Guid?)this;
  1754. case PrimitiveTypeCode.Guid:
  1755. return (Guid)this;
  1756. case PrimitiveTypeCode.Uri:
  1757. return (Uri)this;
  1758. case PrimitiveTypeCode.TimeSpanNullable:
  1759. return (TimeSpan?)this;
  1760. case PrimitiveTypeCode.TimeSpan:
  1761. return (TimeSpan)this;
  1762. #if HAVE_BIG_INTEGER
  1763. case PrimitiveTypeCode.BigIntegerNullable:
  1764. return ToBigIntegerNullable(this);
  1765. case PrimitiveTypeCode.BigInteger:
  1766. return ToBigInteger(this);
  1767. #endif
  1768. }
  1769. }
  1770. return ToObject(objectType, JsonSerializer.CreateDefault());
  1771. }
  1772. /// <summary>
  1773. /// Creates an instance of the specified .NET type from the <see cref="JToken"/> using the specified <see cref="JsonSerializer"/>.
  1774. /// </summary>
  1775. /// <typeparam name="T">The object type that the token will be deserialized to.</typeparam>
  1776. /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used when creating the object.</param>
  1777. /// <returns>The new object created from the JSON value.</returns>
  1778. public T ToObject<T>(JsonSerializer jsonSerializer)
  1779. {
  1780. return (T)ToObject(typeof(T), jsonSerializer);
  1781. }
  1782. /// <summary>
  1783. /// Creates an instance of the specified .NET type from the <see cref="JToken"/> using the specified <see cref="JsonSerializer"/>.
  1784. /// </summary>
  1785. /// <param name="objectType">The object type that the token will be deserialized to.</param>
  1786. /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used when creating the object.</param>
  1787. /// <returns>The new object created from the JSON value.</returns>
  1788. public object ToObject(Type objectType, JsonSerializer jsonSerializer)
  1789. {
  1790. ValidationUtils.ArgumentNotNull(jsonSerializer, nameof(jsonSerializer));
  1791. using (JTokenReader jsonReader = new JTokenReader(this))
  1792. {
  1793. return jsonSerializer.Deserialize(jsonReader, objectType);
  1794. }
  1795. }
  1796. /// <summary>
  1797. /// Creates a <see cref="JToken"/> from a <see cref="JsonReader"/>.
  1798. /// </summary>
  1799. /// <param name="reader">A <see cref="JsonReader"/> positioned at the token to read into this <see cref="JToken"/>.</param>
  1800. /// <returns>
  1801. /// A <see cref="JToken"/> that contains the token and its descendant tokens
  1802. /// that were read from the reader. The runtime type of the token is determined
  1803. /// by the token type of the first token encountered in the reader.
  1804. /// </returns>
  1805. public static JToken ReadFrom(JsonReader reader)
  1806. {
  1807. return ReadFrom(reader, null);
  1808. }
  1809. /// <summary>
  1810. /// Creates a <see cref="JToken"/> from a <see cref="JsonReader"/>.
  1811. /// </summary>
  1812. /// <param name="reader">An <see cref="JsonReader"/> positioned at the token to read into this <see cref="JToken"/>.</param>
  1813. /// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
  1814. /// If this is <c>null</c>, default load settings will be used.</param>
  1815. /// <returns>
  1816. /// A <see cref="JToken"/> that contains the token and its descendant tokens
  1817. /// that were read from the reader. The runtime type of the token is determined
  1818. /// by the token type of the first token encountered in the reader.
  1819. /// </returns>
  1820. public static JToken ReadFrom(JsonReader reader, JsonLoadSettings settings)
  1821. {
  1822. ValidationUtils.ArgumentNotNull(reader, nameof(reader));
  1823. bool hasContent;
  1824. if (reader.TokenType == JsonToken.None)
  1825. {
  1826. hasContent = (settings != null && settings.CommentHandling == CommentHandling.Ignore)
  1827. ? reader.ReadAndMoveToContent()
  1828. : reader.Read();
  1829. }
  1830. else if (reader.TokenType == JsonToken.Comment && settings?.CommentHandling == CommentHandling.Ignore)
  1831. {
  1832. hasContent = reader.ReadAndMoveToContent();
  1833. }
  1834. else
  1835. {
  1836. hasContent = true;
  1837. }
  1838. if (!hasContent)
  1839. {
  1840. throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader.");
  1841. }
  1842. IJsonLineInfo lineInfo = reader as IJsonLineInfo;
  1843. switch (reader.TokenType)
  1844. {
  1845. case JsonToken.StartObject:
  1846. return JObject.Load(reader, settings);
  1847. case JsonToken.StartArray:
  1848. return JArray.Load(reader, settings);
  1849. case JsonToken.StartConstructor:
  1850. return JConstructor.Load(reader, settings);
  1851. case JsonToken.PropertyName:
  1852. return JProperty.Load(reader, settings);
  1853. case JsonToken.String:
  1854. case JsonToken.Integer:
  1855. case JsonToken.Float:
  1856. case JsonToken.Date:
  1857. case JsonToken.Boolean:
  1858. case JsonToken.Bytes:
  1859. JValue v = new JValue(reader.Value);
  1860. v.SetLineInfo(lineInfo, settings);
  1861. return v;
  1862. case JsonToken.Comment:
  1863. v = JValue.CreateComment(reader.Value.ToString());
  1864. v.SetLineInfo(lineInfo, settings);
  1865. return v;
  1866. case JsonToken.Null:
  1867. v = JValue.CreateNull();
  1868. v.SetLineInfo(lineInfo, settings);
  1869. return v;
  1870. case JsonToken.Undefined:
  1871. v = JValue.CreateUndefined();
  1872. v.SetLineInfo(lineInfo, settings);
  1873. return v;
  1874. default:
  1875. throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
  1876. }
  1877. }
  1878. /// <summary>
  1879. /// Load a <see cref="JToken"/> from a string that contains JSON.
  1880. /// </summary>
  1881. /// <param name="json">A <see cref="String"/> that contains JSON.</param>
  1882. /// <returns>A <see cref="JToken"/> populated from the string that contains JSON.</returns>
  1883. public static JToken Parse(string json)
  1884. {
  1885. return Parse(json, null);
  1886. }
  1887. /// <summary>
  1888. /// Load a <see cref="JToken"/> from a string that contains JSON.
  1889. /// </summary>
  1890. /// <param name="json">A <see cref="String"/> that contains JSON.</param>
  1891. /// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
  1892. /// If this is <c>null</c>, default load settings will be used.</param>
  1893. /// <returns>A <see cref="JToken"/> populated from the string that contains JSON.</returns>
  1894. public static JToken Parse(string json, JsonLoadSettings settings)
  1895. {
  1896. using (JsonReader reader = new JsonTextReader(new StringReader(json)))
  1897. {
  1898. JToken t = Load(reader, settings);
  1899. while (reader.Read())
  1900. {
  1901. // Any content encountered here other than a comment will throw in the reader.
  1902. }
  1903. return t;
  1904. }
  1905. }
  1906. /// <summary>
  1907. /// Creates a <see cref="JToken"/> from a <see cref="JsonReader"/>.
  1908. /// </summary>
  1909. /// <param name="reader">A <see cref="JsonReader"/> positioned at the token to read into this <see cref="JToken"/>.</param>
  1910. /// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
  1911. /// If this is <c>null</c>, default load settings will be used.</param>
  1912. /// <returns>
  1913. /// A <see cref="JToken"/> that contains the token and its descendant tokens
  1914. /// that were read from the reader. The runtime type of the token is determined
  1915. /// by the token type of the first token encountered in the reader.
  1916. /// </returns>
  1917. public static JToken Load(JsonReader reader, JsonLoadSettings settings)
  1918. {
  1919. return ReadFrom(reader, settings);
  1920. }
  1921. /// <summary>
  1922. /// Creates a <see cref="JToken"/> from a <see cref="JsonReader"/>.
  1923. /// </summary>
  1924. /// <param name="reader">A <see cref="JsonReader"/> positioned at the token to read into this <see cref="JToken"/>.</param>
  1925. /// <returns>
  1926. /// A <see cref="JToken"/> that contains the token and its descendant tokens
  1927. /// that were read from the reader. The runtime type of the token is determined
  1928. /// by the token type of the first token encountered in the reader.
  1929. /// </returns>
  1930. public static JToken Load(JsonReader reader)
  1931. {
  1932. return Load(reader, null);
  1933. }
  1934. internal void SetLineInfo(IJsonLineInfo lineInfo, JsonLoadSettings settings)
  1935. {
  1936. if (settings != null && settings.LineInfoHandling != LineInfoHandling.Load)
  1937. {
  1938. return;
  1939. }
  1940. if (lineInfo == null || !lineInfo.HasLineInfo())
  1941. {
  1942. return;
  1943. }
  1944. SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
  1945. }
  1946. private class LineInfoAnnotation
  1947. {
  1948. internal readonly int LineNumber;
  1949. internal readonly int LinePosition;
  1950. public LineInfoAnnotation(int lineNumber, int linePosition)
  1951. {
  1952. LineNumber = lineNumber;
  1953. LinePosition = linePosition;
  1954. }
  1955. }
  1956. internal void SetLineInfo(int lineNumber, int linePosition)
  1957. {
  1958. AddAnnotation(new LineInfoAnnotation(lineNumber, linePosition));
  1959. }
  1960. bool IJsonLineInfo.HasLineInfo()
  1961. {
  1962. return (Annotation<LineInfoAnnotation>() != null);
  1963. }
  1964. int IJsonLineInfo.LineNumber
  1965. {
  1966. get
  1967. {
  1968. LineInfoAnnotation annotation = Annotation<LineInfoAnnotation>();
  1969. if (annotation != null)
  1970. {
  1971. return annotation.LineNumber;
  1972. }
  1973. return 0;
  1974. }
  1975. }
  1976. int IJsonLineInfo.LinePosition
  1977. {
  1978. get
  1979. {
  1980. LineInfoAnnotation annotation = Annotation<LineInfoAnnotation>();
  1981. if (annotation != null)
  1982. {
  1983. return annotation.LinePosition;
  1984. }
  1985. return 0;
  1986. }
  1987. }
  1988. /// <summary>
  1989. /// Selects a <see cref="JToken"/> using a JPath expression. Selects the token that matches the object path.
  1990. /// </summary>
  1991. /// <param name="path">
  1992. /// A <see cref="String"/> that contains a JPath expression.
  1993. /// </param>
  1994. /// <returns>A <see cref="JToken"/>, or <c>null</c>.</returns>
  1995. public JToken SelectToken(string path)
  1996. {
  1997. return SelectToken(path, false);
  1998. }
  1999. /// <summary>
  2000. /// Selects a <see cref="JToken"/> using a JPath expression. Selects the token that matches the object path.
  2001. /// </summary>
  2002. /// <param name="path">
  2003. /// A <see cref="String"/> that contains a JPath expression.
  2004. /// </param>
  2005. /// <param name="errorWhenNoMatch">A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.</param>
  2006. /// <returns>A <see cref="JToken"/>.</returns>
  2007. public JToken SelectToken(string path, bool errorWhenNoMatch)
  2008. {
  2009. JPath p = new JPath(path);
  2010. JToken token = null;
  2011. foreach (JToken t in p.Evaluate(this, this, errorWhenNoMatch))
  2012. {
  2013. if (token != null)
  2014. {
  2015. throw new JsonException("Path returned multiple tokens.");
  2016. }
  2017. token = t;
  2018. }
  2019. return token;
  2020. }
  2021. /// <summary>
  2022. /// Selects a collection of elements using a JPath expression.
  2023. /// </summary>
  2024. /// <param name="path">
  2025. /// A <see cref="String"/> that contains a JPath expression.
  2026. /// </param>
  2027. /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the selected elements.</returns>
  2028. public IEnumerable<JToken> SelectTokens(string path)
  2029. {
  2030. return SelectTokens(path, false);
  2031. }
  2032. /// <summary>
  2033. /// Selects a collection of elements using a JPath expression.
  2034. /// </summary>
  2035. /// <param name="path">
  2036. /// A <see cref="String"/> that contains a JPath expression.
  2037. /// </param>
  2038. /// <param name="errorWhenNoMatch">A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.</param>
  2039. /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the selected elements.</returns>
  2040. public IEnumerable<JToken> SelectTokens(string path, bool errorWhenNoMatch)
  2041. {
  2042. JPath p = new JPath(path);
  2043. return p.Evaluate(this, this, errorWhenNoMatch);
  2044. }
  2045. #if !NET20
  2046. /// <summary>
  2047. /// Returns the <see cref="DynamicMetaObject"/> responsible for binding operations performed on this object.
  2048. /// </summary>
  2049. /// <param name="parameter">The expression tree representation of the runtime value.</param>
  2050. /// <returns>
  2051. /// The <see cref="DynamicMetaObject"/> to bind this object.
  2052. /// </returns>
  2053. protected virtual DynamicMetaObject GetMetaObject(Expression parameter)
  2054. {
  2055. return new DynamicProxyMetaObject<JToken>(parameter, this, new DynamicProxy<JToken>());
  2056. }
  2057. /// <summary>
  2058. /// Returns the <see cref="DynamicMetaObject"/> responsible for binding operations performed on this object.
  2059. /// </summary>
  2060. /// <param name="parameter">The expression tree representation of the runtime value.</param>
  2061. /// <returns>
  2062. /// The <see cref="DynamicMetaObject"/> to bind this object.
  2063. /// </returns>
  2064. DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
  2065. {
  2066. return GetMetaObject(parameter);
  2067. }
  2068. #endif
  2069. object ICloneable.Clone()
  2070. {
  2071. return DeepClone();
  2072. }
  2073. /// <summary>
  2074. /// Creates a new instance of the <see cref="JToken"/>. All child tokens are recursively cloned.
  2075. /// </summary>
  2076. /// <returns>A new instance of the <see cref="JToken"/>.</returns>
  2077. public JToken DeepClone()
  2078. {
  2079. return CloneToken();
  2080. }
  2081. /// <summary>
  2082. /// Adds an object to the annotation list of this <see cref="JToken"/>.
  2083. /// </summary>
  2084. /// <param name="annotation">The annotation to add.</param>
  2085. public void AddAnnotation(object annotation)
  2086. {
  2087. if (annotation == null)
  2088. {
  2089. throw new ArgumentNullException(nameof(annotation));
  2090. }
  2091. if (_annotations == null)
  2092. {
  2093. _annotations = (annotation is object[]) ? new[] { annotation } : annotation;
  2094. }
  2095. else
  2096. {
  2097. if (!(_annotations is object[] annotations))
  2098. {
  2099. _annotations = new[] { _annotations, annotation };
  2100. }
  2101. else
  2102. {
  2103. int index = 0;
  2104. while (index < annotations.Length && annotations[index] != null)
  2105. {
  2106. index++;
  2107. }
  2108. if (index == annotations.Length)
  2109. {
  2110. Array.Resize(ref annotations, index * 2);
  2111. _annotations = annotations;
  2112. }
  2113. annotations[index] = annotation;
  2114. }
  2115. }
  2116. }
  2117. /// <summary>
  2118. /// Get the first annotation object of the specified type from this <see cref="JToken"/>.
  2119. /// </summary>
  2120. /// <typeparam name="T">The type of the annotation to retrieve.</typeparam>
  2121. /// <returns>The first annotation object that matches the specified type, or <c>null</c> if no annotation is of the specified type.</returns>
  2122. public T Annotation<T>() where T : class
  2123. {
  2124. if (_annotations != null)
  2125. {
  2126. if (!(_annotations is object[] annotations))
  2127. {
  2128. return (_annotations as T);
  2129. }
  2130. for (int i = 0; i < annotations.Length; i++)
  2131. {
  2132. object annotation = annotations[i];
  2133. if (annotation == null)
  2134. {
  2135. break;
  2136. }
  2137. if (annotation is T local)
  2138. {
  2139. return local;
  2140. }
  2141. }
  2142. }
  2143. return default(T);
  2144. }
  2145. /// <summary>
  2146. /// Gets the first annotation object of the specified type from this <see cref="JToken"/>.
  2147. /// </summary>
  2148. /// <param name="type">The <see cref="Type"/> of the annotation to retrieve.</param>
  2149. /// <returns>The first annotation object that matches the specified type, or <c>null</c> if no annotation is of the specified type.</returns>
  2150. public object Annotation(Type type)
  2151. {
  2152. if (type == null)
  2153. {
  2154. throw new ArgumentNullException(nameof(type));
  2155. }
  2156. if (_annotations != null)
  2157. {
  2158. if (!(_annotations is object[] annotations))
  2159. {
  2160. if (type.IsInstanceOfType(_annotations))
  2161. {
  2162. return _annotations;
  2163. }
  2164. }
  2165. else
  2166. {
  2167. for (int i = 0; i < annotations.Length; i++)
  2168. {
  2169. object o = annotations[i];
  2170. if (o == null)
  2171. {
  2172. break;
  2173. }
  2174. if (type.IsInstanceOfType(o))
  2175. {
  2176. return o;
  2177. }
  2178. }
  2179. }
  2180. }
  2181. return null;
  2182. }
  2183. /// <summary>
  2184. /// Gets a collection of annotations of the specified type for this <see cref="JToken"/>.
  2185. /// </summary>
  2186. /// <typeparam name="T">The type of the annotations to retrieve.</typeparam>
  2187. /// <returns>An <see cref="IEnumerable{T}"/> that contains the annotations for this <see cref="JToken"/>.</returns>
  2188. public IEnumerable<T> Annotations<T>() where T : class
  2189. {
  2190. if (_annotations == null)
  2191. {
  2192. yield break;
  2193. }
  2194. if (_annotations is object[] annotations)
  2195. {
  2196. for (int i = 0; i < annotations.Length; i++)
  2197. {
  2198. object o = annotations[i];
  2199. if (o == null)
  2200. {
  2201. break;
  2202. }
  2203. if (o is T casted)
  2204. {
  2205. yield return casted;
  2206. }
  2207. }
  2208. yield break;
  2209. }
  2210. if (!(_annotations is T annotation))
  2211. {
  2212. yield break;
  2213. }
  2214. yield return annotation;
  2215. }
  2216. /// <summary>
  2217. /// Gets a collection of annotations of the specified type for this <see cref="JToken"/>.
  2218. /// </summary>
  2219. /// <param name="type">The <see cref="Type"/> of the annotations to retrieve.</param>
  2220. /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="Object"/> that contains the annotations that match the specified type for this <see cref="JToken"/>.</returns>
  2221. public IEnumerable<object> Annotations(Type type)
  2222. {
  2223. if (type == null)
  2224. {
  2225. throw new ArgumentNullException(nameof(type));
  2226. }
  2227. if (_annotations == null)
  2228. {
  2229. yield break;
  2230. }
  2231. if (_annotations is object[] annotations)
  2232. {
  2233. for (int i = 0; i < annotations.Length; i++)
  2234. {
  2235. object o = annotations[i];
  2236. if (o == null)
  2237. {
  2238. break;
  2239. }
  2240. if (type.IsInstanceOfType(o))
  2241. {
  2242. yield return o;
  2243. }
  2244. }
  2245. yield break;
  2246. }
  2247. if (!type.IsInstanceOfType(_annotations))
  2248. {
  2249. yield break;
  2250. }
  2251. yield return _annotations;
  2252. }
  2253. /// <summary>
  2254. /// Removes the annotations of the specified type from this <see cref="JToken"/>.
  2255. /// </summary>
  2256. /// <typeparam name="T">The type of annotations to remove.</typeparam>
  2257. public void RemoveAnnotations<T>() where T : class
  2258. {
  2259. if (_annotations != null)
  2260. {
  2261. if (!(_annotations is object[] annotations))
  2262. {
  2263. if (_annotations is T)
  2264. {
  2265. _annotations = null;
  2266. }
  2267. }
  2268. else
  2269. {
  2270. int index = 0;
  2271. int keepCount = 0;
  2272. while (index < annotations.Length)
  2273. {
  2274. object obj2 = annotations[index];
  2275. if (obj2 == null)
  2276. {
  2277. break;
  2278. }
  2279. if (!(obj2 is T))
  2280. {
  2281. annotations[keepCount++] = obj2;
  2282. }
  2283. index++;
  2284. }
  2285. if (keepCount != 0)
  2286. {
  2287. while (keepCount < index)
  2288. {
  2289. annotations[keepCount++] = null;
  2290. }
  2291. }
  2292. else
  2293. {
  2294. _annotations = null;
  2295. }
  2296. }
  2297. }
  2298. }
  2299. /// <summary>
  2300. /// Removes the annotations of the specified type from this <see cref="JToken"/>.
  2301. /// </summary>
  2302. /// <param name="type">The <see cref="Type"/> of annotations to remove.</param>
  2303. public void RemoveAnnotations(Type type)
  2304. {
  2305. if (type == null)
  2306. {
  2307. throw new ArgumentNullException(nameof(type));
  2308. }
  2309. if (_annotations != null)
  2310. {
  2311. if (!(_annotations is object[] annotations))
  2312. {
  2313. if (type.IsInstanceOfType(_annotations))
  2314. {
  2315. _annotations = null;
  2316. }
  2317. }
  2318. else
  2319. {
  2320. int index = 0;
  2321. int keepCount = 0;
  2322. while (index < annotations.Length)
  2323. {
  2324. object o = annotations[index];
  2325. if (o == null)
  2326. {
  2327. break;
  2328. }
  2329. if (!type.IsInstanceOfType(o))
  2330. {
  2331. annotations[keepCount++] = o;
  2332. }
  2333. index++;
  2334. }
  2335. if (keepCount != 0)
  2336. {
  2337. while (keepCount < index)
  2338. {
  2339. annotations[keepCount++] = null;
  2340. }
  2341. }
  2342. else
  2343. {
  2344. _annotations = null;
  2345. }
  2346. }
  2347. }
  2348. }
  2349. }
  2350. }