IJsonReader.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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="callback">A callback that will be invoked for each encountered dictionary key</param>
  57. void ParseDictionary(Type keyType, Action<object> callback);
  58. /// <summary>
  59. /// Reads an array from the input stream
  60. /// </summary>
  61. /// <param name="callback">A callback that will be invoked as each array element is encounters</param>
  62. void ParseArray(Action callback);
  63. /// <summary>
  64. /// Gets the literal kind of the current stream token
  65. /// </summary>
  66. /// <returns></returns>
  67. LiteralKind GetLiteralKind();
  68. /// <summary>
  69. /// Gets a string literal from the JSON stream
  70. /// </summary>
  71. /// <returns></returns>
  72. string GetLiteralString();
  73. /// <summary>
  74. /// Moves to the next token in the input stream
  75. /// </summary>
  76. void NextToken();
  77. }
  78. /// <summary>
  79. /// Helper functions for working with IJsonReader
  80. /// </summary>
  81. public static class IJsonReaderExtensions
  82. {
  83. /// <summary>
  84. /// Read a literal number
  85. /// </summary>
  86. /// <typeparam name="T">The number type</typeparam>
  87. /// <param name="reader">The reader to read from</param>
  88. /// <returns>A number of specified type, or throws an InvalidDataException</returns>
  89. public static T ReadLiteralNumber<T>(this IJsonReader reader)
  90. {
  91. return (T)ReadLiteralNumber(reader, typeof(T));
  92. }
  93. /// <summary>
  94. /// Reads a dictionary from the input stream
  95. /// </summary>
  96. /// <param name="callback">A callback that will be invoked for each encountered dictionary key</param>
  97. public static void ParseDictionary(this IJsonReader reader, Action<string> callback)
  98. {
  99. reader.ParseDictionary<string>(callback);
  100. }
  101. /// <summary>
  102. /// Reads a dictionary from the input stream
  103. /// </summary>
  104. /// <param name="callback">A callback that will be invoked for each encountered dictionary key</param>
  105. public static void ParseDictionary<T>(this IJsonReader reader, Action<T> callback)
  106. {
  107. reader.ParseDictionary(typeof(T), (o) => callback((T)o));
  108. }
  109. /// <summary>
  110. /// Read a literal number
  111. /// </summary>
  112. /// <param name="reader">The reader to read from</param>
  113. /// <param name="type">The number type to return</param>
  114. /// <returns>A number of specified type, or throws an InvalidDataException</returns>
  115. public static object ReadLiteralNumber(this IJsonReader reader, Type type)
  116. {
  117. switch (reader.GetLiteralKind())
  118. {
  119. case LiteralKind.SignedInteger:
  120. case LiteralKind.UnsignedInteger:
  121. {
  122. var str = reader.GetLiteralString();
  123. if (str.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
  124. {
  125. var tempValue = Convert.ToUInt64(str.Substring(2), 16);
  126. object val = Convert.ChangeType(tempValue, type, CultureInfo.InvariantCulture);
  127. reader.NextToken();
  128. return val;
  129. }
  130. else
  131. {
  132. object val = Convert.ChangeType(str, type, CultureInfo.InvariantCulture);
  133. reader.NextToken();
  134. return val;
  135. }
  136. }
  137. case LiteralKind.FloatingPoint:
  138. {
  139. object val = Convert.ChangeType(reader.GetLiteralString(), type, CultureInfo.InvariantCulture);
  140. reader.NextToken();
  141. return val;
  142. }
  143. }
  144. throw new InvalidDataException("expected a numeric literal");
  145. }
  146. }
  147. }