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.

138 lines
6.0 KiB

  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. #if HAVE_ASYNC
  26. using System;
  27. using System.Globalization;
  28. #if HAVE_BIG_INTEGER
  29. using System.Numerics;
  30. #endif
  31. using System.Threading;
  32. using System.Threading.Tasks;
  33. using Newtonsoft.Json.Utilities;
  34. namespace Newtonsoft.Json.Linq
  35. {
  36. internal partial class JValue
  37. {
  38. /// <summary>
  39. /// Writes this token to a <see cref="JsonWriter"/> asynchronously.
  40. /// </summary>
  41. /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
  42. /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
  43. /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
  44. /// <returns>A <see cref="Task"/> that represents the asynchronous write operation.</returns>
  45. public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters)
  46. {
  47. if (converters != null && converters.Length > 0 && _value != null)
  48. {
  49. JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType());
  50. if (matchingConverter != null && matchingConverter.CanWrite)
  51. {
  52. // TODO: Call WriteJsonAsync when it exists.
  53. matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault());
  54. return AsyncUtils.CompletedTask;
  55. }
  56. }
  57. switch (_valueType)
  58. {
  59. case JTokenType.Comment:
  60. return writer.WriteCommentAsync(_value?.ToString(), cancellationToken);
  61. case JTokenType.Raw:
  62. return writer.WriteRawValueAsync(_value?.ToString(), cancellationToken);
  63. case JTokenType.Null:
  64. return writer.WriteNullAsync(cancellationToken);
  65. case JTokenType.Undefined:
  66. return writer.WriteUndefinedAsync(cancellationToken);
  67. case JTokenType.Integer:
  68. if (_value is int i)
  69. {
  70. return writer.WriteValueAsync(i, cancellationToken);
  71. }
  72. if (_value is long l)
  73. {
  74. return writer.WriteValueAsync(l, cancellationToken);
  75. }
  76. if (_value is ulong ul)
  77. {
  78. return writer.WriteValueAsync(ul, cancellationToken);
  79. }
  80. #if HAVE_BIG_INTEGER
  81. if (_value is BigInteger integer)
  82. {
  83. return writer.WriteValueAsync(integer, cancellationToken);
  84. }
  85. #endif
  86. return writer.WriteValueAsync(Convert.ToInt64(_value, CultureInfo.InvariantCulture), cancellationToken);
  87. case JTokenType.Float:
  88. if (_value is decimal dec)
  89. {
  90. return writer.WriteValueAsync(dec, cancellationToken);
  91. }
  92. if (_value is double d)
  93. {
  94. return writer.WriteValueAsync(d, cancellationToken);
  95. }
  96. if (_value is float f)
  97. {
  98. return writer.WriteValueAsync(f, cancellationToken);
  99. }
  100. return writer.WriteValueAsync(Convert.ToDouble(_value, CultureInfo.InvariantCulture), cancellationToken);
  101. case JTokenType.String:
  102. return writer.WriteValueAsync(_value?.ToString(), cancellationToken);
  103. case JTokenType.Boolean:
  104. return writer.WriteValueAsync(Convert.ToBoolean(_value, CultureInfo.InvariantCulture), cancellationToken);
  105. case JTokenType.Date:
  106. if (_value is DateTimeOffset offset)
  107. {
  108. return writer.WriteValueAsync(offset, cancellationToken);
  109. }
  110. return writer.WriteValueAsync(Convert.ToDateTime(_value, CultureInfo.InvariantCulture), cancellationToken);
  111. case JTokenType.Bytes:
  112. return writer.WriteValueAsync((byte[])_value, cancellationToken);
  113. case JTokenType.Guid:
  114. return writer.WriteValueAsync(_value != null ? (Guid?)_value : null, cancellationToken);
  115. case JTokenType.TimeSpan:
  116. return writer.WriteValueAsync(_value != null ? (TimeSpan?)_value : null, cancellationToken);
  117. case JTokenType.Uri:
  118. return writer.WriteValueAsync((Uri)_value, cancellationToken);
  119. }
  120. throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(Type), _valueType, "Unexpected token type.");
  121. }
  122. }
  123. }
  124. #endif