IJsonReader.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // JsonKit v0.5 - A simple but flexible Json library in a single .cs file.
  2. //
  3. // Copyright (C) 2014 Topten Software (contact@toptensoftware.com) All rights reserved.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this product
  6. // except in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the
  11. // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  12. // either express or implied. See the License for the specific language governing permissions
  13. // and limitations under the License.
  14. using System;
  15. using System.Globalization;
  16. using System.IO;
  17. using System.Reflection;
  18. namespace Topten.JsonKit
  19. {
  20. /// <summary>
  21. /// Provides a reader for JSON data
  22. /// </summary>
  23. [Obfuscation(Exclude=true, ApplyToMembers=true)]
  24. public interface IJsonReader
  25. {
  26. /// <summary>
  27. /// Parses an object of specified type from the JSON stream
  28. /// </summary>
  29. /// <param name="type">The type to be parsed</param>
  30. /// <returns>A reference to the loaded instance</returns>
  31. object Parse(Type type);
  32. /// <summary>
  33. /// Parses an object of specified type from the JSON stream
  34. /// </summary>
  35. /// <typeparam name="T">The type to be parsed</typeparam>
  36. /// <returns>A reference to the loaded instance</returns>
  37. T Parse<T>();
  38. /// <summary>
  39. /// Parses from a JSON stream into an existing object instance
  40. /// </summary>
  41. /// <param name="into">The target object</param>
  42. void ParseInto(object into);
  43. /// <summary>
  44. /// The current token in the input JSON stream
  45. /// </summary>
  46. Token CurrentToken { get; }
  47. /// <summary>
  48. /// Reads a literal value from the JSON stream
  49. /// </summary>
  50. /// <param name="converter">A converter function to convert the value</param>
  51. /// <returns>The parsed and converted value</returns>
  52. object ReadLiteral(Func<object, object> converter);
  53. /// <summary>
  54. /// Reads a dictinary from the input stream
  55. /// </summary>
  56. /// <param name="keyType">The type of the dictionary key</param>
  57. /// <param name="callback">A callback that will be invoked for each encountered dictionary key</param>
  58. void ParseDictionary(Type keyType, Action<object> callback);
  59. /// <summary>
  60. /// Reads an array from the input stream
  61. /// </summary>
  62. /// <param name="callback">A callback that will be invoked as each array element is encounters</param>
  63. void ParseArray(Action callback);
  64. /// <summary>
  65. /// Gets the literal kind of the current stream token
  66. /// </summary>
  67. /// <returns></returns>
  68. LiteralKind GetLiteralKind();
  69. /// <summary>
  70. /// Gets a string literal from the JSON stream
  71. /// </summary>
  72. /// <returns></returns>
  73. string GetLiteralString();
  74. /// <summary>
  75. /// Moves to the next token in the input stream
  76. /// </summary>
  77. void NextToken();
  78. }
  79. /// <summary>
  80. /// Helper functions for working with IJsonReader
  81. /// </summary>
  82. public static class IJsonReaderExtensions
  83. {
  84. /// <summary>
  85. /// Read a literal number
  86. /// </summary>
  87. /// <typeparam name="T">The number type</typeparam>
  88. /// <param name="reader">The reader to read from</param>
  89. /// <returns>A number of specified type, or throws an InvalidDataException</returns>
  90. public static T ReadLiteralNumber<T>(this IJsonReader reader)
  91. {
  92. return (T)ReadLiteralNumber(reader, typeof(T));
  93. }
  94. /// <summary>
  95. /// Reads a dictionary from the input stream
  96. /// </summary>
  97. /// <param name="reader">The IJsonReader instance</param>
  98. /// <param name="callback">A callback that will be invoked for each encountered dictionary key</param>
  99. public static void ParseDictionary(this IJsonReader reader, Action<string> callback)
  100. {
  101. reader.ParseDictionary<string>(callback);
  102. }
  103. /// <summary>
  104. /// Reads a dictionary from the input stream
  105. /// </summary>
  106. /// <param name="reader">The IJsonReader instance</param>
  107. /// <param name="callback">A callback that will be invoked for each encountered dictionary key</param>
  108. public static void ParseDictionary<T>(this IJsonReader reader, Action<T> callback)
  109. {
  110. reader.ParseDictionary(typeof(T), (o) => callback((T)o));
  111. }
  112. /// <summary>
  113. /// Read a literal number
  114. /// </summary>
  115. /// <param name="reader">The reader to read from</param>
  116. /// <param name="type">The number type to return</param>
  117. /// <returns>A number of specified type, or throws an InvalidDataException</returns>
  118. public static object ReadLiteralNumber(this IJsonReader reader, Type type)
  119. {
  120. switch (reader.GetLiteralKind())
  121. {
  122. case LiteralKind.String:
  123. var value = Convert.ChangeType(reader.GetLiteralString(), type, CultureInfo.InvariantCulture);
  124. reader.NextToken();
  125. return value;
  126. case LiteralKind.SignedInteger:
  127. case LiteralKind.UnsignedInteger:
  128. {
  129. var str = reader.GetLiteralString();
  130. if (str.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
  131. {
  132. var tempValue = Convert.ToUInt64(str.Substring(2), 16);
  133. object val = Convert.ChangeType(tempValue, type, CultureInfo.InvariantCulture);
  134. reader.NextToken();
  135. return val;
  136. }
  137. else
  138. {
  139. object val = Convert.ChangeType(str, type, CultureInfo.InvariantCulture);
  140. reader.NextToken();
  141. return val;
  142. }
  143. }
  144. case LiteralKind.FloatingPoint:
  145. {
  146. object val = Convert.ChangeType(reader.GetLiteralString(), type, CultureInfo.InvariantCulture);
  147. reader.NextToken();
  148. return val;
  149. }
  150. }
  151. throw new InvalidDataException("expected a numeric literal");
  152. }
  153. }
  154. }