PageRenderTime 66ms CodeModel.GetById 11ms app.highlight 48ms RepoModel.GetById 1ms 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
  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.
 13namespace 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
 31	[Scenario]
 32	public class When_serializing_messages_with_json_dot_net
 33	{
 34		string _body;
 35		Envelope _envelope;
 36		TestMessage _message;
 37		JsonSerializer _serializer;
 38		XDocument _xml;
 39		static Type _proxyType = InterfaceImplementationBuilder.GetProxyFor(typeof(MessageA));
 40		JsonSerializer _deserializer;
 41
 42
 43		[When]
 44		public void Serializing_messages_with_json_dot_net()
 45		{
 46			_message = new TestMessage
 47				{
 48					Name = "Joe",
 49					Details = new List<TestMessageDetail>
 50						{
 51							new TestMessageDetail {Item = "A", Value = 27.5d},
 52							new TestMessageDetail {Item = "B", Value = 13.5d},
 53						},
 54                    DateTimeProperty = new DateTime(2014,03,05,01,53,04,193),
 55                    DateTimeStringProperty = "2014-03-05T01:53:04.193",
 56                    Dictionary = new Dictionary<string, string>()
 57                    {
 58                        {"string-datetime-property","2014-03-05T01:53:04.193"}
 59                    }
 60				};
 61
 62			_envelope = new Envelope
 63				{
 64					Message = _message,
 65				};
 66
 67			_envelope.MessageType.Add(_message.GetType().ToMessageName());
 68			_envelope.MessageType.Add(typeof (MessageA).ToMessageName());
 69			_envelope.MessageType.Add(typeof (MessageB).ToMessageName());
 70
 71		    _serializer = JsonMessageSerializer.Serializer;
 72            _deserializer = JsonMessageSerializer.Deserializer;
 73
 74			using (var memoryStream = new MemoryStream())
 75			using (var writer = new StreamWriter(memoryStream))
 76			using (var jsonWriter = new JsonTextWriter(writer))
 77			{
 78				jsonWriter.Formatting = Formatting.Indented;
 79				_serializer.Serialize(jsonWriter, _envelope);
 80
 81				writer.Flush();
 82				_body = Encoding.UTF8.GetString(memoryStream.ToArray());
 83			}
 84			
 85			_xml = JsonConvert.DeserializeXNode(_body, "envelope");
 86		}
 87
 88		[Then, Explicit]
 89		public void Show_me_the_message()
 90		{
 91			Trace.WriteLine(_body);
 92			Trace.WriteLine(_xml.ToString());
 93		}
 94
 95		[Then]
 96		public void Should_be_able_to_ressurect_the_message()
 97		{
 98			Envelope result;
 99			using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
100			using (var reader = new StreamReader(memoryStream))
101			using (var jsonReader = new JsonTextReader(reader))
102			{
103				result = _deserializer.Deserialize<Envelope>(jsonReader);
104			}
105
106			result.MessageType.Count.ShouldEqual(3);
107			result.MessageType[0].ShouldEqual(typeof (TestMessage).ToMessageName());
108			result.MessageType[1].ShouldEqual(typeof (MessageA).ToMessageName());
109			result.MessageType[2].ShouldEqual(typeof (MessageB).ToMessageName());
110			result.Headers.Count.ShouldEqual(0);
111		}
112
113		[Then]
114		public void Should_be_able_to_suck_out_an_interface()
115		{
116			Envelope result;
117			using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
118			using (var reader = new StreamReader(memoryStream))
119			using (var jsonReader = new JsonTextReader(reader))
120			{
121				result = _deserializer.Deserialize<Envelope>(jsonReader);
122			}
123
124			using(var jsonReader = new JTokenReader(result.Message as JToken))
125			{
126				Type proxyType = InterfaceImplementationBuilder.GetProxyFor(typeof (MessageA));
127				var message = (MessageA) FastActivator.Create(proxyType);
128
129				_serializer.Populate(jsonReader, message);
130
131				message.Name.ShouldEqual("Joe");
132			}
133		}
134
135		[Then]
136		public void Should_be_able_to_suck_out_an_object()
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
146			using(var jsonReader = new JTokenReader(result.Message as JToken))
147			{
148				var message = (TestMessage) _serializer.Deserialize(jsonReader, typeof (TestMessage));
149
150				message.Name.ShouldEqual("Joe");
151				message.Details.Count.ShouldEqual(2);
152			}
153		}
154
155        [Then]
156        public void Should_roundtrip_dates_as_string_or_datetime()
157        {
158            Envelope result;
159            using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
160            using (var reader = new StreamReader(memoryStream))
161            using (var jsonReader = new JsonTextReader(reader))
162            {
163                result = _deserializer.Deserialize<Envelope>(jsonReader);
164            }
165
166            using (var jsonReader = new JTokenReader(result.Message as JToken))
167            {
168                var message = (TestMessage)_serializer.Deserialize(jsonReader, typeof(TestMessage));
169
170                // DateTimes are properly serialized / deserialized
171                // however, string properties containing a date-string are somehow
172                // converted to a Datetime somewhere in deserialization
173                // fixed by adding DateParseHandling = DateParseHandling.None to serializer settings
174                message.DateTimeProperty.ShouldEqual(new DateTime(2014, 03, 05, 01, 53, 04, 193),"Round ripping DateTimeProperty failed");
175                message.DateTimeStringProperty.ShouldEqual("2014-03-05T01:53:04.193","Roundtripping DateTimeStringProperty failed");
176                message.Dictionary["string-datetime-property"].ShouldEqual("2014-03-05T01:53:04.193","Roundtripping datetimestring in dictionary failed");
177            }
178        }
179
180		[Then]
181		public void Should_be_able_to_ressurect_the_message_from_xml()
182		{
183			XDocument document = XDocument.Parse(_xml.ToString());
184			Trace.WriteLine(_xml.ToString());
185			string body = JsonConvert.SerializeXNode(document, Formatting.None, true);
186			Trace.WriteLine(body);
187			var result = JsonConvert.DeserializeObject<Envelope>(body, new JsonSerializerSettings
188				{
189					Converters = new List<JsonConverter>(new JsonConverter[]{new ListJsonConverter()}),
190					NullValueHandling = NullValueHandling.Ignore,
191					DefaultValueHandling = DefaultValueHandling.Ignore,
192					MissingMemberHandling = MissingMemberHandling.Ignore,
193					ObjectCreationHandling = ObjectCreationHandling.Auto,
194					ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
195					ContractResolver = new CamelCasePropertyNamesContractResolver(),
196				});
197
198			result.MessageType.Count.ShouldEqual(3);
199			result.MessageType[0].ShouldEqual(typeof (TestMessage).ToMessageName());
200			result.MessageType[1].ShouldEqual(typeof (MessageA).ToMessageName());
201			result.MessageType[2].ShouldEqual(typeof (MessageB).ToMessageName());
202			result.Headers.Count.ShouldEqual(0);
203		}
204
205		[Then]
206		public void Serialization_speed()
207		{
208			//warm it up
209			for (int i = 0; i < 10; i++)
210			{
211				DoSerialize();
212				DoDeserialize();
213			}
214
215			Stopwatch timer = Stopwatch.StartNew();
216
217			const int iterations = 50000;
218
219			for (int i = 0; i < iterations; i++)
220			{
221				DoSerialize();
222			}
223
224			timer.Stop();
225
226			long perSecond = iterations*1000/timer.ElapsedMilliseconds;
227
228			string msg = string.Format("Serialize: {0}ms, Rate: {1} m/s", timer.ElapsedMilliseconds, perSecond);
229			Trace.WriteLine(msg);
230
231			timer = Stopwatch.StartNew();
232
233			for (int i = 0; i < 50000; i++)
234			{
235				DoDeserialize();
236			}
237
238			timer.Stop();
239
240			perSecond = iterations*1000/timer.ElapsedMilliseconds;
241
242			msg = string.Format("Deserialize: {0}ms, Rate: {1} m/s", timer.ElapsedMilliseconds, perSecond);
243			Trace.WriteLine(msg);
244		}
245
246		void DoSerialize()
247		{
248			using (var memoryStream = new MemoryStream())
249			using (var writer = new StreamWriter(memoryStream))
250			using (var jsonWriter = new JsonTextWriter(writer))
251			{
252				jsonWriter.Formatting = Formatting.Indented;
253				_serializer.Serialize(jsonWriter, _envelope);
254
255				writer.Flush();
256				_body = Encoding.UTF8.GetString(memoryStream.ToArray());
257			}
258		}
259
260		void DoDeserialize()
261		{
262			Envelope result;
263			using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(_body), false))
264			using (var reader = new StreamReader(memoryStream))
265			using (var jsonReader = new JsonTextReader(reader))
266			{
267				result = _deserializer.Deserialize<Envelope>(jsonReader);
268			}
269
270			using (var jsonReader = new JTokenReader(result.Message as JToken))
271			{
272				var message = (MessageA)FastActivator.Create(_proxyType);
273
274				_serializer.Populate(jsonReader, message);
275
276			}
277		}
278
279		class Envelope
280		{
281			public Envelope()
282			{
283				Headers = new Dictionary<string, string>();
284				MessageType = new List<string>();
285			}
286
287			public IDictionary<string, string> Headers { get; set; }
288			public object Message { get; set; }
289			public IList<string> MessageType { get; set; }
290		}
291
292		class TestMessageDetail
293		{
294			public string Item { get; set; }
295			public double Value { get; set; }
296		}
297
298		class TestMessage :
299			MessageA
300		{
301			public string Address { get; set; }
302			public IList<TestMessageDetail> Details { get; set; }
303			public int Level { get; set; }
304			public string Name { get; set; }
305            public DateTime DateTimeProperty { get; set; }
306            public string DateTimeStringProperty { get; set; }
307            public Dictionary<string,string> Dictionary { get; set; } 
308		}
309
310
311		public static object Convert(string s)
312		{
313			object obj = JsonConvert.DeserializeObject(s);
314			if (obj is string)
315			{
316				return obj as string;
317			}
318
319			return ConvertJson((JToken) obj);
320		}
321
322		public interface MessageA
323		{
324			string Name { get; }
325		}
326
327		public interface MessageB
328		{
329			string Address { get; }
330			string Name { get; }
331		}
332
333		static object ConvertJson(JToken token)
334		{
335			if (token is JValue)
336			{
337				return ((JValue) token).Value;
338			}
339
340			if (token is JObject)
341			{
342				IDictionary<string, object> expando = new Dictionary<string, object>();
343
344				(from childToken in (token) where childToken is JProperty select childToken as JProperty).ToList().ForEach(
345					property => { expando.Add(property.Name, ConvertJson(property.Value)); });
346				return expando;
347			}
348
349			if (token is JArray)
350			{
351				return (token).Select(ConvertJson).ToList();
352			}
353
354			throw new ArgumentException(string.Format("Unknown token type '{0}'", token.GetType()), "token");
355		}
356	}
357
358    [TestFixture]
359  public class Using_JsonConverterAttribute_on_a_class :
360    SerializationTest<JsonMessageSerializer>
361  {
362    public class ModifyWhenSerializingConverter : JsonConverter
363    {
364      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
365      {
366        writer.WriteStartObject();
367
368        writer.WritePropertyName("value");
369        writer.WriteValue("Monster");
370
371        writer.WriteEndObject();
372      }
373
374      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
375      {
376        reader.Read();
377        reader.Value.ShouldEqual("value");
378        reader.Read();
379        var value = (string)reader.Value;
380        return new MessageA { Value = value };
381      }
382
383      public override bool CanConvert(Type objectType)
384      {
385        return typeof(MessageA).IsAssignableFrom(objectType);
386      }
387    }
388
389    public class ModifyWhenDeserializingConverter : JsonConverter
390    {
391      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
392      {
393        var testMessage = (MessageB)value;
394        writer.WriteStartObject();
395
396        writer.WritePropertyName("value");
397        writer.WriteValue(testMessage.Value);
398
399        writer.WriteEndObject();
400      }
401
402      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
403      {
404        return new MessageB { Value = "Monster" };
405      }
406
407      public override bool CanConvert(Type objectType)
408      {
409        return typeof(MessageB).IsAssignableFrom(objectType);
410      }
411    }
412
413    [JsonConverter(typeof(ModifyWhenSerializingConverter))]
414    public class MessageA
415    {
416      public string Value { get; set; }
417    }
418
419    [JsonConverter(typeof(ModifyWhenDeserializingConverter))]
420    public class MessageB
421    {
422      public string Value { get; set; }
423    }
424
425    [Test]
426    public void Should_use_converter_for_serialization()
427    {
428      var obj = new MessageA { Value = "Joe" };
429
430      MessageA result = SerializeAndReturn(obj);
431
432      result.Value.ShouldEqual("Monster");
433    }
434
435    [Test]
436    public void Should_use_converter_for_deserialization()
437    {
438      var obj = new MessageB { Value = "Joe" };
439
440      MessageB result = SerializeAndReturn(obj);
441
442      result.Value.ShouldEqual("Monster");
443    }
444  }
445
446  [TestFixture]
447  public class Using_JsonConverterAttribute_on_a_property :
448    SerializationTest<JsonMessageSerializer>
449  {
450    public class ModifyWhenSerializingConverter : JsonConverter
451    {
452      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
453      {
454        writer.WriteValue("Monster");
455      }
456
457      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
458      {
459        return reader.Value;
460      }
461
462      public override bool CanConvert(Type objectType)
463      {
464        return typeof(string).IsAssignableFrom(objectType);
465      }
466    }
467
468    public class ModifyWhenDeserializingConverter : JsonConverter
469    {
470      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
471      {
472        writer.WriteValue((string)value);
473      }
474
475      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
476      {
477        return "Monster";
478      }
479
480      public override bool CanConvert(Type objectType)
481      {
482        return typeof(string).IsAssignableFrom(objectType);
483      }
484    }
485
486    public class SimpleMessage
487    {
488      [JsonConverter(typeof(ModifyWhenSerializingConverter))]
489      public string ValueA { get; set; }
490
491      [JsonConverter(typeof(ModifyWhenDeserializingConverter))]
492      public string ValueB { get; set; }
493    }
494
495    [Test]
496    public void Should_use_converter_for_serialization()
497    {
498      var obj = new SimpleMessage { ValueA = "Joe" };
499
500      SimpleMessage result = SerializeAndReturn(obj);
501
502      result.ValueA.ShouldEqual("Monster");
503    }
504
505    [Test]
506    public void Should_use_converter_for_deserialization()
507    {
508      var obj = new SimpleMessage { ValueB = "Joe" };
509
510      SimpleMessage result = SerializeAndReturn(obj);
511
512      result.ValueB.ShouldEqual("Monster");
513    }
514  }
515}