PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Raven.Abstractions/Extensions/JsonExtensions.cs

http://github.com/ayende/ravendb
C# | 389 lines | 292 code | 60 blank | 37 comment | 25 complexity | 5c7b26e80667bfe5d159d54648dcb925 MD5 | raw file
Possible License(s): GPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, Apache-2.0, BSD-3-Clause, CC-BY-SA-3.0
  1. //-----------------------------------------------------------------------
  2. // <copyright file="JsonExtensions.cs" company="Hibernating Rhinos LTD">
  3. // Copyright (c) Hibernating Rhinos LTD. All rights reserved.
  4. // </copyright>
  5. //-----------------------------------------------------------------------
  6. using System;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Reflection;
  10. using System.Runtime.CompilerServices;
  11. using System.Text;
  12. using Raven.Abstractions.Json;
  13. using Raven.Abstractions.Linq;
  14. using Raven.Imports.Newtonsoft.Json;
  15. using Raven.Imports.Newtonsoft.Json.Bson;
  16. using Raven.Imports.Newtonsoft.Json.Serialization;
  17. using Raven.Json.Linq;
  18. using System.Collections.Generic;
  19. using Raven.Abstractions.Connection;
  20. using Raven.Abstractions.Util;
  21. using Raven.Abstractions.Util.MiniMetrics;
  22. namespace Raven.Abstractions.Extensions
  23. {
  24. /// <summary>
  25. /// Json extensions
  26. /// </summary>
  27. public static class JsonExtensions
  28. {
  29. public static MeterMetric JsonStreamDeserializationsPerSecond;
  30. public static MeterMetric JsonStreamDeserializedBytesPerSecond;
  31. public static MeterMetric JsonStreamSerializationsPerSecond;
  32. public static MeterMetric JsonStreamSerializedBytesPerSecond;
  33. static JsonExtensions()
  34. {
  35. JsonStreamDeserializationsPerSecond = new MeterMetric(MetricsScheduler.Instance);
  36. JsonStreamDeserializedBytesPerSecond = new MeterMetric(MetricsScheduler.Instance);
  37. JsonStreamSerializationsPerSecond = new MeterMetric(MetricsScheduler.Instance);
  38. JsonStreamSerializedBytesPerSecond = new MeterMetric(MetricsScheduler.Instance);
  39. }
  40. public static RavenJObject ToJObject(object result)
  41. {
  42. var dynamicJsonObject = result as Linq.IDynamicJsonObject;
  43. if (dynamicJsonObject != null)
  44. return dynamicJsonObject.Inner;
  45. if (result is string || result is ValueType)
  46. return new RavenJObject {{"Value", new RavenJValue(result)}};
  47. if (result is DynamicNullObject)
  48. return null;
  49. return RavenJObject.FromObject(result, CreateDefaultJsonSerializer());
  50. }
  51. public static RavenJArray ToJArray<T>(IEnumerable<T> result)
  52. {
  53. return (RavenJArray) RavenJArray.FromObject(result, CreateDefaultJsonSerializer());
  54. }
  55. /// <summary>
  56. /// Convert a byte array to a RavenJObject
  57. /// </summary>
  58. public static RavenJObject ToJObject(this byte[] self)
  59. {
  60. using (var stream = new MemoryStream(self))
  61. return ToJObject(stream);
  62. }
  63. /// <summary>
  64. /// Convert a byte array to a RavenJObject
  65. /// </summary>
  66. public static RavenJObject ToJObject(this Stream self)
  67. {
  68. var streamWithCachedHeader = new StreamWithCachedHeader(self, 5);
  69. using (var counting = new CountingStream(streamWithCachedHeader))
  70. {
  71. if (IsJson(streamWithCachedHeader))
  72. {
  73. // note that we intentionally don't close it here
  74. var jsonReader = new JsonTextReader(new StreamReader(counting));
  75. var ravenJObject = RavenJObject.Load(jsonReader);
  76. RegisterJsonStreamDeserializationMetrics((int)counting.NumberOfReadBytes);
  77. return ravenJObject;
  78. }
  79. RegisterJsonStreamDeserializationMetrics((int)counting.NumberOfReadBytes);
  80. var deserializedObject = RavenJObject.Load(new BsonReader(counting)
  81. {
  82. DateTimeKindHandling = DateTimeKind.Utc,
  83. });
  84. return deserializedObject;
  85. }
  86. }
  87. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  88. private static void RegisterJsonStreamDeserializationMetrics(int numberOfReadBytes)
  89. {
  90. JsonStreamDeserializationsPerSecond.Mark();
  91. JsonStreamDeserializedBytesPerSecond.Mark(numberOfReadBytes);
  92. }
  93. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  94. private static void RegisterJsonStreamSerializationMetrics(int size)
  95. {
  96. JsonStreamSerializationsPerSecond.Mark();
  97. JsonStreamSerializedBytesPerSecond.Mark(size);
  98. }
  99. /// <summary>
  100. /// Convert a RavenJToken to a byte array
  101. /// </summary>
  102. public static void WriteTo(this RavenJToken self, Stream stream)
  103. {
  104. using (var counting = new CountingStream(stream))
  105. {
  106. using (var streamWriter = new StreamWriter(counting, Encoding.UTF8, 1024, true))
  107. using (var jsonWriter = new JsonTextWriter(streamWriter))
  108. {
  109. jsonWriter.Formatting = Formatting.None;
  110. jsonWriter.DateFormatHandling = DateFormatHandling.IsoDateFormat;
  111. jsonWriter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
  112. jsonWriter.DateFormatString = Default.DateTimeFormatsToWrite;
  113. self.WriteTo(jsonWriter, Default.Converters);
  114. }
  115. RegisterJsonStreamSerializationMetrics((int)counting.NumberOfWrittenBytes);
  116. }
  117. }
  118. public static IEnumerable<string> EnumerateJsonObjects(this StreamReader input, char openChar = '{', char closeChar = '}')
  119. {
  120. var accumulator = new StringBuilder();
  121. int count = 0;
  122. bool gotRecord = false;
  123. while (!input.EndOfStream)
  124. {
  125. char c = (char) input.Read();
  126. if (c == openChar)
  127. {
  128. gotRecord = true;
  129. count++;
  130. }
  131. else if (c == closeChar)
  132. {
  133. count--;
  134. }
  135. accumulator.Append(c);
  136. if (count != 0 || !gotRecord)
  137. continue;
  138. // now we are not within a block so
  139. string result = accumulator.ToString();
  140. accumulator.Clear();
  141. gotRecord = false;
  142. yield return result;
  143. }
  144. }
  145. /// <summary>
  146. /// Deserialize a <param name="self"/> to an instance of <typeparam name="T"/>
  147. /// </summary>
  148. public static T JsonDeserialization<T>(this byte[] self)
  149. {
  150. return (T) CreateDefaultJsonSerializer().Deserialize(new BsonReader(new MemoryStream(self)), typeof(T));
  151. }
  152. /// <summary>
  153. /// Deserialize a <param name="self"/> to an instance of<typeparam name="T"/>
  154. /// </summary>
  155. public static T JsonDeserialization<T>(this RavenJToken self)
  156. {
  157. return (T) CreateDefaultJsonSerializer().Deserialize(new RavenJTokenReader(self), typeof(T));
  158. }
  159. /// <summary>
  160. /// Deserialize a <param name="self"/> to a list of instances of<typeparam name="T"/>
  161. /// </summary>
  162. public static T[] JsonDeserialization<T>(this RavenJArray self)
  163. {
  164. var serializer = CreateDefaultJsonSerializer();
  165. return self.Select(x => (T) serializer.Deserialize(new RavenJTokenReader(x), typeof(T))).ToArray();
  166. }
  167. /// <summary>
  168. /// Deserialize a <param name="self"/> to an instance of<typeparam name="T"/>
  169. /// </summary>
  170. public static T JsonDeserialization<T>(this StreamReader self)
  171. {
  172. return CreateDefaultJsonSerializer().Deserialize<T>(self);
  173. }
  174. /// <summary>
  175. /// Deserialize a <param name="stream"/> to an instance of<typeparam name="T"/>
  176. /// </summary>
  177. public static T JsonDeserialization<T>(this Stream stream)
  178. {
  179. using (var reader = new StreamReader(stream))
  180. {
  181. return reader.JsonDeserialization<T>();
  182. }
  183. }
  184. public static T Deserialize<T>(this JsonSerializer self, TextReader reader)
  185. {
  186. return (T) self.Deserialize(reader, typeof(T));
  187. }
  188. private static readonly IContractResolver contractResolver = new DefaultServerContractResolver(shareCache: true)
  189. {
  190. DefaultMembersSearchFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
  191. };
  192. private class DefaultServerContractResolver : DefaultContractResolver
  193. {
  194. public DefaultServerContractResolver(bool shareCache)
  195. : base(shareCache)
  196. {
  197. }
  198. protected override System.Collections.Generic.List<MemberInfo> GetSerializableMembers(Type objectType)
  199. {
  200. var serializableMembers = base.GetSerializableMembers(objectType);
  201. foreach (var toRemove in serializableMembers
  202. .Where(MembersToFilterOut)
  203. .ToArray())
  204. {
  205. serializableMembers.Remove(toRemove);
  206. }
  207. return serializableMembers;
  208. }
  209. private static bool MembersToFilterOut(MemberInfo info)
  210. {
  211. if (info is EventInfo)
  212. return true;
  213. var fieldInfo = info as FieldInfo;
  214. if (fieldInfo != null && !fieldInfo.IsPublic)
  215. return true;
  216. return info.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Any();
  217. }
  218. }
  219. public static JsonSerializer CreateDefaultJsonSerializer()
  220. {
  221. var jsonSerializer = new JsonSerializer
  222. {
  223. DateParseHandling = DateParseHandling.None,
  224. ContractResolver = contractResolver,
  225. Converters = Default.Converters
  226. };
  227. return jsonSerializer;
  228. }
  229. private static bool IsJson(StreamWithCachedHeader stream)
  230. {
  231. // in BSON first four bytes are int32 which represents content length
  232. // as result we can't distigush between json and bson based on first 4 bytes
  233. // in bson 5-th byte is value type
  234. var bsonType = stream.Header[4];
  235. return stream.ActualHeaderSize < 5 || bsonType > (byte) BsonType.RavenDBCustomFloat;
  236. }
  237. }
  238. internal class StreamWithCachedHeader : Stream
  239. {
  240. private readonly Stream inner;
  241. public int ActualHeaderSize { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; private set; }
  242. private int headerSizePosition;
  243. public byte[] Header { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; private set; }
  244. private bool passedHeader;
  245. private int read;
  246. public StreamWithCachedHeader(Stream stream, int headerSize)
  247. {
  248. inner = stream;
  249. Header = new byte[headerSize];
  250. CacheHeader(stream, Header, headerSize);
  251. }
  252. private void CacheHeader(Stream stream, byte[] buffer, int headerSize)
  253. {
  254. ActualHeaderSize = stream.Read(buffer, 0, headerSize);
  255. }
  256. public override void Flush()
  257. {
  258. inner.Flush();
  259. }
  260. public override int ReadByte()
  261. {
  262. if (passedHeader)
  263. return inner.ReadByte();
  264. var b = Header[headerSizePosition++];
  265. passedHeader = headerSizePosition >= ActualHeaderSize;
  266. return b;
  267. }
  268. public override long Seek(long offset, SeekOrigin origin)
  269. {
  270. return inner.Seek(offset, origin);
  271. }
  272. public override void SetLength(long value)
  273. {
  274. inner.SetLength(value);
  275. }
  276. public override int Read(byte[] buffer, int offset, int count)
  277. {
  278. if (passedHeader)
  279. return inner.Read(buffer, offset, count);
  280. if (count <= ActualHeaderSize - headerSizePosition)
  281. {
  282. Buffer.BlockCopy(Header, headerSizePosition, buffer, 0, count);
  283. headerSizePosition += count;
  284. passedHeader = headerSizePosition >= ActualHeaderSize;
  285. return count;
  286. }
  287. Buffer.BlockCopy(Header, headerSizePosition, buffer, 0, ActualHeaderSize - headerSizePosition);
  288. var newCount = count - ActualHeaderSize + headerSizePosition;
  289. var r = inner.Read(buffer, offset + ActualHeaderSize, newCount);
  290. var currentRead = ActualHeaderSize - headerSizePosition + r;
  291. read += currentRead;
  292. headerSizePosition += currentRead;
  293. passedHeader = read >= ActualHeaderSize;
  294. return currentRead;
  295. }
  296. public override void Write(byte[] buffer, int offset, int count)
  297. {
  298. inner.Write(buffer, offset, count);
  299. }
  300. public override bool CanRead
  301. {
  302. get { return inner.CanRead; }
  303. }
  304. public override bool CanSeek
  305. {
  306. get { return inner.CanSeek; }
  307. }
  308. public override bool CanWrite
  309. {
  310. get { return inner.CanWrite; }
  311. }
  312. public override long Length
  313. {
  314. get { return inner.Length; }
  315. }
  316. public override long Position
  317. {
  318. get { return inner.Position; }
  319. set { inner.Position = value; }
  320. }
  321. #if !DNXCORE50
  322. public override void Close()
  323. {
  324. if (inner != null)
  325. inner.Close();
  326. }
  327. #endif
  328. }
  329. }