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.

175 lines
7.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. using System.Threading;
  29. using System.Threading.Tasks;
  30. using Newtonsoft.Json.Utilities;
  31. namespace Newtonsoft.Json.Linq
  32. {
  33. internal abstract partial class JContainer
  34. {
  35. internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings options, CancellationToken cancellationToken = default(CancellationToken))
  36. {
  37. ValidationUtils.ArgumentNotNull(reader, nameof(reader));
  38. int startDepth = reader.Depth;
  39. if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
  40. {
  41. throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
  42. }
  43. await ReadContentFromAsync(reader, options, cancellationToken).ConfigureAwait(false);
  44. if (reader.Depth > startDepth)
  45. {
  46. throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
  47. }
  48. }
  49. private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default(CancellationToken))
  50. {
  51. IJsonLineInfo lineInfo = reader as IJsonLineInfo;
  52. JContainer parent = this;
  53. do
  54. {
  55. if ((parent as JProperty)?.Value != null)
  56. {
  57. if (parent == this)
  58. {
  59. return;
  60. }
  61. parent = parent.Parent;
  62. }
  63. switch (reader.TokenType)
  64. {
  65. case JsonToken.None:
  66. // new reader. move to actual content
  67. break;
  68. case JsonToken.StartArray:
  69. JArray a = new JArray();
  70. a.SetLineInfo(lineInfo, settings);
  71. parent.Add(a);
  72. parent = a;
  73. break;
  74. case JsonToken.EndArray:
  75. if (parent == this)
  76. {
  77. return;
  78. }
  79. parent = parent.Parent;
  80. break;
  81. case JsonToken.StartObject:
  82. JObject o = new JObject();
  83. o.SetLineInfo(lineInfo, settings);
  84. parent.Add(o);
  85. parent = o;
  86. break;
  87. case JsonToken.EndObject:
  88. if (parent == this)
  89. {
  90. return;
  91. }
  92. parent = parent.Parent;
  93. break;
  94. case JsonToken.StartConstructor:
  95. JConstructor constructor = new JConstructor(reader.Value.ToString());
  96. constructor.SetLineInfo(lineInfo, settings);
  97. parent.Add(constructor);
  98. parent = constructor;
  99. break;
  100. case JsonToken.EndConstructor:
  101. if (parent == this)
  102. {
  103. return;
  104. }
  105. parent = parent.Parent;
  106. break;
  107. case JsonToken.String:
  108. case JsonToken.Integer:
  109. case JsonToken.Float:
  110. case JsonToken.Date:
  111. case JsonToken.Boolean:
  112. case JsonToken.Bytes:
  113. JValue v = new JValue(reader.Value);
  114. v.SetLineInfo(lineInfo, settings);
  115. parent.Add(v);
  116. break;
  117. case JsonToken.Comment:
  118. if (settings != null && settings.CommentHandling == CommentHandling.Load)
  119. {
  120. v = JValue.CreateComment(reader.Value.ToString());
  121. v.SetLineInfo(lineInfo, settings);
  122. parent.Add(v);
  123. }
  124. break;
  125. case JsonToken.Null:
  126. v = JValue.CreateNull();
  127. v.SetLineInfo(lineInfo, settings);
  128. parent.Add(v);
  129. break;
  130. case JsonToken.Undefined:
  131. v = JValue.CreateUndefined();
  132. v.SetLineInfo(lineInfo, settings);
  133. parent.Add(v);
  134. break;
  135. case JsonToken.PropertyName:
  136. string propertyName = reader.Value.ToString();
  137. JProperty property = new JProperty(propertyName);
  138. property.SetLineInfo(lineInfo, settings);
  139. JObject parentObject = (JObject)parent;
  140. // handle multiple properties with the same name in JSON
  141. JProperty existingPropertyWithName = parentObject.Property(propertyName);
  142. if (existingPropertyWithName == null)
  143. {
  144. parent.Add(property);
  145. }
  146. else
  147. {
  148. existingPropertyWithName.Replace(property);
  149. }
  150. parent = property;
  151. break;
  152. default:
  153. throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
  154. }
  155. } while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false));
  156. }
  157. }
  158. }
  159. #endif