PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/MassTransit.Tests/Serialization/JsonSerialization_Specs.cs

https://github.com/ed-801/MassTransit
C# | 515 lines | 410 code | 88 blank | 17 comment | 7 complexity | c5e1dd788ff9704f546299be16e54967 MD5 | raw file
Possible License(s): Apache-2.0
  1. // Copyright 2007-2011 Chris Patterson, Dru Sellers, Travis Smith, et. al.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  4. // this file except in compliance with the License. You may obtain a copy of the
  5. // License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software distributed
  10. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  11. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  12. // specific language governing permissions and limitations under the License.
  13. namespace MassTransit.Tests.Serialization
  14. {
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.IO;
  19. using System.Linq;
  20. using System.Text;
  21. using System.Xml.Linq;
  22. using Magnum.Reflection;
  23. using Magnum.TestFramework;
  24. using MassTransit.Serialization;
  25. using Newtonsoft.Json;
  26. using Newtonsoft.Json.Converters;
  27. using Newtonsoft.Json.Linq;
  28. using Newtonsoft.Json.Serialization;
  29. using NUnit.Framework;
  30. [Scenario]
  31. public class When_serializing_messages_with_json_dot_net
  32. {
  33. string _body;
  34. Envelope _envelope;
  35. TestMessage _message;
  36. JsonSerializer _serializer;
  37. XDocument _xml;
  38. static Type _proxyType = InterfaceImplementationBuilder.GetProxyFor(typeof(MessageA));
  39. JsonSerializer _deserializer;
  40. [When]
  41. public void Serializing_messages_with_json_dot_net()
  42. {
  43. _message = new TestMessage
  44. {
  45. Name = "Joe",
  46. Details = new List<TestMessageDetail>
  47. {
  48. new TestMessageDetail {Item = "A", Value = 27.5d},
  49. new TestMessageDetail {Item = "B", Value = 13.5d},
  50. },
  51. DateTimeProperty = new DateTime(2014,03,05,01,53,04,193),
  52. DateTimeStringProperty = "2014-03-05T01:53:04.193",
  53. Dictionary = new Dictionary<string, string>()
  54. {
  55. {"string-datetime-property","2014-03-05T01:53:04.193"}
  56. }
  57. };
  58. _envelope = new Envelope
  59. {
  60. Message = _message,
  61. };
  62. _envelope.MessageType.Add(_message.GetType().ToMessageName());
  63. _envelope.MessageType.Add(typeof (MessageA).ToMessageName());
  64. _envelope.MessageType.Add(typeof (MessageB).ToMessageName());
  65. _serializer = JsonMessageSerializer.Serializer;
  66. _deserializer = JsonMessageSerializer.Deserializer;
  67. using (var memoryStream = new MemoryStream())
  68. using (var writer = new StreamWriter(memoryStream))
  69. using (var jsonWriter = new JsonTextWriter(writer))
  70. {
  71. jsonWriter.Formatting = Formatting.Indented;
  72. _serializer.Serialize(jsonWriter, _envelope);
  73. writer.Flush();
  74. _body = Encoding.UTF8.GetString(memoryStream.ToArray());
  75. }
  76. _xml = JsonConvert.DeserializeXNode(_body, "envelope");
  77. }
  78. [Then, Explicit]
  79. public void Show_me_the_message()
  80. {
  81. Trace.WriteLine(_body);
  82. Trace.WriteLine(_xml.ToString());
  83. }
  84. [Then]
  85. public void Should_be_able_to_ressurect_the_message()
  86. {
  87. Envelope result;
  88. using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
  89. using (var reader = new StreamReader(memoryStream))
  90. using (var jsonReader = new JsonTextReader(reader))
  91. {
  92. result = _deserializer.Deserialize<Envelope>(jsonReader);
  93. }
  94. result.MessageType.Count.ShouldEqual(3);
  95. result.MessageType[0].ShouldEqual(typeof (TestMessage).ToMessageName());
  96. result.MessageType[1].ShouldEqual(typeof (MessageA).ToMessageName());
  97. result.MessageType[2].ShouldEqual(typeof (MessageB).ToMessageName());
  98. result.Headers.Count.ShouldEqual(0);
  99. }
  100. [Then]
  101. public void Should_be_able_to_suck_out_an_interface()
  102. {
  103. Envelope result;
  104. using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
  105. using (var reader = new StreamReader(memoryStream))
  106. using (var jsonReader = new JsonTextReader(reader))
  107. {
  108. result = _deserializer.Deserialize<Envelope>(jsonReader);
  109. }
  110. using(var jsonReader = new JTokenReader(result.Message as JToken))
  111. {
  112. Type proxyType = InterfaceImplementationBuilder.GetProxyFor(typeof (MessageA));
  113. var message = (MessageA) FastActivator.Create(proxyType);
  114. _serializer.Populate(jsonReader, message);
  115. message.Name.ShouldEqual("Joe");
  116. }
  117. }
  118. [Then]
  119. public void Should_be_able_to_suck_out_an_object()
  120. {
  121. Envelope result;
  122. using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
  123. using (var reader = new StreamReader(memoryStream))
  124. using (var jsonReader = new JsonTextReader(reader))
  125. {
  126. result = _deserializer.Deserialize<Envelope>(jsonReader);
  127. }
  128. using(var jsonReader = new JTokenReader(result.Message as JToken))
  129. {
  130. var message = (TestMessage) _serializer.Deserialize(jsonReader, typeof (TestMessage));
  131. message.Name.ShouldEqual("Joe");
  132. message.Details.Count.ShouldEqual(2);
  133. }
  134. }
  135. [Then]
  136. public void Should_roundtrip_dates_as_string_or_datetime()
  137. {
  138. Envelope result;
  139. using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
  140. using (var reader = new StreamReader(memoryStream))
  141. using (var jsonReader = new JsonTextReader(reader))
  142. {
  143. result = _deserializer.Deserialize<Envelope>(jsonReader);
  144. }
  145. using (var jsonReader = new JTokenReader(result.Message as JToken))
  146. {
  147. var message = (TestMessage)_serializer.Deserialize(jsonReader, typeof(TestMessage));
  148. // DateTimes are properly serialized / deserialized
  149. // however, string properties containing a date-string are somehow
  150. // converted to a Datetime somewhere in deserialization
  151. // fixed by adding DateParseHandling = DateParseHandling.None to serializer settings
  152. message.DateTimeProperty.ShouldEqual(new DateTime(2014, 03, 05, 01, 53, 04, 193),"Round ripping DateTimeProperty failed");
  153. message.DateTimeStringProperty.ShouldEqual("2014-03-05T01:53:04.193","Roundtripping DateTimeStringProperty failed");
  154. message.Dictionary["string-datetime-property"].ShouldEqual("2014-03-05T01:53:04.193","Roundtripping datetimestring in dictionary failed");
  155. }
  156. }
  157. [Then]
  158. public void Should_be_able_to_ressurect_the_message_from_xml()
  159. {
  160. XDocument document = XDocument.Parse(_xml.ToString());
  161. Trace.WriteLine(_xml.ToString());
  162. string body = JsonConvert.SerializeXNode(document, Formatting.None, true);
  163. Trace.WriteLine(body);
  164. var result = JsonConvert.DeserializeObject<Envelope>(body, new JsonSerializerSettings
  165. {
  166. Converters = new List<JsonConverter>(new JsonConverter[]{new ListJsonConverter()}),
  167. NullValueHandling = NullValueHandling.Ignore,
  168. DefaultValueHandling = DefaultValueHandling.Ignore,
  169. MissingMemberHandling = MissingMemberHandling.Ignore,
  170. ObjectCreationHandling = ObjectCreationHandling.Auto,
  171. ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
  172. ContractResolver = new CamelCasePropertyNamesContractResolver(),
  173. });
  174. result.MessageType.Count.ShouldEqual(3);
  175. result.MessageType[0].ShouldEqual(typeof (TestMessage).ToMessageName());
  176. result.MessageType[1].ShouldEqual(typeof (MessageA).ToMessageName());
  177. result.MessageType[2].ShouldEqual(typeof (MessageB).ToMessageName());
  178. result.Headers.Count.ShouldEqual(0);
  179. }
  180. [Then]
  181. public void Serialization_speed()
  182. {
  183. //warm it up
  184. for (int i = 0; i < 10; i++)
  185. {
  186. DoSerialize();
  187. DoDeserialize();
  188. }
  189. Stopwatch timer = Stopwatch.StartNew();
  190. const int iterations = 50000;
  191. for (int i = 0; i < iterations; i++)
  192. {
  193. DoSerialize();
  194. }
  195. timer.Stop();
  196. long perSecond = iterations*1000/timer.ElapsedMilliseconds;
  197. string msg = string.Format("Serialize: {0}ms, Rate: {1} m/s", timer.ElapsedMilliseconds, perSecond);
  198. Trace.WriteLine(msg);
  199. timer = Stopwatch.StartNew();
  200. for (int i = 0; i < 50000; i++)
  201. {
  202. DoDeserialize();
  203. }
  204. timer.Stop();
  205. perSecond = iterations*1000/timer.ElapsedMilliseconds;
  206. msg = string.Format("Deserialize: {0}ms, Rate: {1} m/s", timer.ElapsedMilliseconds, perSecond);
  207. Trace.WriteLine(msg);
  208. }
  209. void DoSerialize()
  210. {
  211. using (var memoryStream = new MemoryStream())
  212. using (var writer = new StreamWriter(memoryStream))
  213. using (var jsonWriter = new JsonTextWriter(writer))
  214. {
  215. jsonWriter.Formatting = Formatting.Indented;
  216. _serializer.Serialize(jsonWriter, _envelope);
  217. writer.Flush();
  218. _body = Encoding.UTF8.GetString(memoryStream.ToArray());
  219. }
  220. }
  221. void DoDeserialize()
  222. {
  223. Envelope result;
  224. using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
  225. using (var reader = new StreamReader(memoryStream))
  226. using (var jsonReader = new JsonTextReader(reader))
  227. {
  228. result = _deserializer.Deserialize<Envelope>(jsonReader);
  229. }
  230. using (var jsonReader = new JTokenReader(result.Message as JToken))
  231. {
  232. var message = (MessageA)FastActivator.Create(_proxyType);
  233. _serializer.Populate(jsonReader, message);
  234. }
  235. }
  236. class Envelope
  237. {
  238. public Envelope()
  239. {
  240. Headers = new Dictionary<string, string>();
  241. MessageType = new List<string>();
  242. }
  243. public IDictionary<string, string> Headers { get; set; }
  244. public object Message { get; set; }
  245. public IList<string> MessageType { get; set; }
  246. }
  247. class TestMessageDetail
  248. {
  249. public string Item { get; set; }
  250. public double Value { get; set; }
  251. }
  252. class TestMessage :
  253. MessageA
  254. {
  255. public string Address { get; set; }
  256. public IList<TestMessageDetail> Details { get; set; }
  257. public int Level { get; set; }
  258. public string Name { get; set; }
  259. public DateTime DateTimeProperty { get; set; }
  260. public string DateTimeStringProperty { get; set; }
  261. public Dictionary<string,string> Dictionary { get; set; }
  262. }
  263. public static object Convert(string s)
  264. {
  265. object obj = JsonConvert.DeserializeObject(s);
  266. if (obj is string)
  267. {
  268. return obj as string;
  269. }
  270. return ConvertJson((JToken) obj);
  271. }
  272. public interface MessageA
  273. {
  274. string Name { get; }
  275. }
  276. public interface MessageB
  277. {
  278. string Address { get; }
  279. string Name { get; }
  280. }
  281. static object ConvertJson(JToken token)
  282. {
  283. if (token is JValue)
  284. {
  285. return ((JValue) token).Value;
  286. }
  287. if (token is JObject)
  288. {
  289. IDictionary<string, object> expando = new Dictionary<string, object>();
  290. (from childToken in (token) where childToken is JProperty select childToken as JProperty).ToList().ForEach(
  291. property => { expando.Add(property.Name, ConvertJson(property.Value)); });
  292. return expando;
  293. }
  294. if (token is JArray)
  295. {
  296. return (token).Select(ConvertJson).ToList();
  297. }
  298. throw new ArgumentException(string.Format("Unknown token type '{0}'", token.GetType()), "token");
  299. }
  300. }
  301. [TestFixture]
  302. public class Using_JsonConverterAttribute_on_a_class :
  303. SerializationTest<JsonMessageSerializer>
  304. {
  305. public class ModifyWhenSerializingConverter : JsonConverter
  306. {
  307. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  308. {
  309. writer.WriteStartObject();
  310. writer.WritePropertyName("value");
  311. writer.WriteValue("Monster");
  312. writer.WriteEndObject();
  313. }
  314. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  315. {
  316. reader.Read();
  317. reader.Value.ShouldEqual("value");
  318. reader.Read();
  319. var value = (string)reader.Value;
  320. return new MessageA { Value = value };
  321. }
  322. public override bool CanConvert(Type objectType)
  323. {
  324. return typeof(MessageA).IsAssignableFrom(objectType);
  325. }
  326. }
  327. public class ModifyWhenDeserializingConverter : JsonConverter
  328. {
  329. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  330. {
  331. var testMessage = (MessageB)value;
  332. writer.WriteStartObject();
  333. writer.WritePropertyName("value");
  334. writer.WriteValue(testMessage.Value);
  335. writer.WriteEndObject();
  336. }
  337. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  338. {
  339. return new MessageB { Value = "Monster" };
  340. }
  341. public override bool CanConvert(Type objectType)
  342. {
  343. return typeof(MessageB).IsAssignableFrom(objectType);
  344. }
  345. }
  346. [JsonConverter(typeof(ModifyWhenSerializingConverter))]
  347. public class MessageA
  348. {
  349. public string Value { get; set; }
  350. }
  351. [JsonConverter(typeof(ModifyWhenDeserializingConverter))]
  352. public class MessageB
  353. {
  354. public string Value { get; set; }
  355. }
  356. [Test]
  357. public void Should_use_converter_for_serialization()
  358. {
  359. var obj = new MessageA { Value = "Joe" };
  360. MessageA result = SerializeAndReturn(obj);
  361. result.Value.ShouldEqual("Monster");
  362. }
  363. [Test]
  364. public void Should_use_converter_for_deserialization()
  365. {
  366. var obj = new MessageB { Value = "Joe" };
  367. MessageB result = SerializeAndReturn(obj);
  368. result.Value.ShouldEqual("Monster");
  369. }
  370. }
  371. [TestFixture]
  372. public class Using_JsonConverterAttribute_on_a_property :
  373. SerializationTest<JsonMessageSerializer>
  374. {
  375. public class ModifyWhenSerializingConverter : JsonConverter
  376. {
  377. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  378. {
  379. writer.WriteValue("Monster");
  380. }
  381. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  382. {
  383. return reader.Value;
  384. }
  385. public override bool CanConvert(Type objectType)
  386. {
  387. return typeof(string).IsAssignableFrom(objectType);
  388. }
  389. }
  390. public class ModifyWhenDeserializingConverter : JsonConverter
  391. {
  392. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  393. {
  394. writer.WriteValue((string)value);
  395. }
  396. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  397. {
  398. return "Monster";
  399. }
  400. public override bool CanConvert(Type objectType)
  401. {
  402. return typeof(string).IsAssignableFrom(objectType);
  403. }
  404. }
  405. public class SimpleMessage
  406. {
  407. [JsonConverter(typeof(ModifyWhenSerializingConverter))]
  408. public string ValueA { get; set; }
  409. [JsonConverter(typeof(ModifyWhenDeserializingConverter))]
  410. public string ValueB { get; set; }
  411. }
  412. [Test]
  413. public void Should_use_converter_for_serialization()
  414. {
  415. var obj = new SimpleMessage { ValueA = "Joe" };
  416. SimpleMessage result = SerializeAndReturn(obj);
  417. result.ValueA.ShouldEqual("Monster");
  418. }
  419. [Test]
  420. public void Should_use_converter_for_deserialization()
  421. {
  422. var obj = new SimpleMessage { ValueB = "Joe" };
  423. SimpleMessage result = SerializeAndReturn(obj);
  424. result.ValueB.ShouldEqual("Monster");
  425. }
  426. }
  427. }