Sample Tests

Feb 1, 2010 at 4:23 PM

I created some tests that serialized different types of objects and thought I would share that with you to see if you could update this code to use this to show how to get this to work if there is custom json code is needed.The complex tests fail given that json doesnt support it without more work . I think it all should really be handled automatically without any custom code given its all strait forward classes but if there is custom json code needed this would help to show how to handle all these situations. I also include some performance tests with json and the .net binary serializer to compare the performance but json seems to be about 3 times slower than the .net binary serializer. Im not sure if you have a profiler but I could profile it if you like to identify the performance bottlenecks. I also have a test with the protocol buffers .net code but that has a lot more problems serializing complex types and doesnt have a lot of extension points to try and get around it so json.net is the closest to handling complex types and I suspect it doesnt need too much more work to automatically support this.

Let me know if you can do that anyhow since this would give a good reference for others when they need to deal with these types of situations.

Sample Test code:

 

SerializationTests.cs class
public class SerializationTests
{
      [Serializable]
      public class TestSerializationSimpleClass
      {
         [JsonProperty]
         private int m_int;

         [JsonProperty]
         private string m_string;

         [JsonProperty]
         private double m_double;

         [JsonProperty]
         private DateTime m_dateTime;

         [JsonProperty]
         private IList<double> m_doubles = new List<double>();

         [JsonProperty]
         private IDictionary<int, double> m_doublesDicIntIndex = new Dictionary<int, double>();

         public int Int
         {
            get { return m_int; }
            set { m_int = value; }
         }

         public string String
         {
            get { return m_string; }
            set { m_string = value; }
         }

         public double Double
         {
            get { return m_double; }
            set { m_double = value; }
         }

         public IList<double> Doubles
         {
            get { return m_doubles; }
            set { m_doubles = value; }
         }

         public IDictionary<int, double> DoublesDicIntIndex
         {
            get { return m_doublesDicIntIndex; }
            set { m_doublesDicIntIndex = value; }
         }

         public DateTime DateTime
         {
            get { return m_dateTime; }
            set { m_dateTime = value; }
         }
      }

      [JsonObject(MemberSerialization.OptIn)]
      [Serializable]
      public class TestSerializationComplexClass : TestSerializationSimpleClass
      {
         [JsonProperty]
         private IDictionary<double, TestSerializationComplexClass> m_DicClassValue = new Dictionary<double, TestSerializationComplexClass>();

         [JsonProperty]
         private IDictionary<TestSerializationComplexClass, double> m_DicClassIndex = new Dictionary<TestSerializationComplexClass, double>();

         [JsonProperty]
         private IDictionary<double, List<TestSerializationComplexClass>> m_DicListValue = new Dictionary<double, List<TestSerializationComplexClass>>();

         [JsonProperty]
         private ClassStruct m_struct;

         [JsonProperty]
         private IList<SerializationAbstractClass> m_abstractList = new List<SerializationAbstractClass>();
        
         [JsonProperty]
         private IList<Type> m_types = new List<Type>();

         [JsonProperty]
         private IDictionary<string, Type> m_dicTypeValue = new Dictionary<string, Type>();

         [JsonProperty]
         private IDictionary<string, ClassStruct> m_structs = new Dictionary<string, ClassStruct>();

         public TestSerializationComplexClass()
         {

         }


         public IDictionary<TestSerializationComplexClass, double> DicClassIndex
         {
            get { return m_DicClassIndex; }
            set { m_DicClassIndex = value; }
         }

         public IDictionary<double, TestSerializationComplexClass> DicClassValue
         {
            get { return m_DicClassValue; }
            set { m_DicClassValue = value; }
         }

         public IDictionary<double, List<TestSerializationComplexClass>> DicListValue
         {
            get { return m_DicListValue; }
            set { m_DicListValue = value; }
         }

         public ClassStruct Struct
         {
            get { return m_struct; }
            set { m_struct = value; }
         }

         public IList<Type> Types
         {
            get { return m_types; }
            set { m_types = value; }
         }

         public IDictionary<string, Type> DicTypeValue
         {
            get { return m_dicTypeValue; }
            set { m_dicTypeValue = value; }
         }
 
         public IDictionary<string, ClassStruct> Structs
         {
            get { return m_structs; }
            set { m_structs = value; }
         }

         public IList<SerializationAbstractClass> AbstractList
         {
            get { return m_abstractList; }
            set { m_abstractList = value; }
         }
      }

      [Serializable]
      public struct ClassStruct
      {
         [JsonProperty]
         private int m_int1;

         [JsonIgnore]
         public int Int1
         {
            get { return m_int1; }
            set { m_int1 = value; }
         }

      }

      [Serializable]
      [JsonObject(MemberSerialization.OptIn)]
      public abstract class SerializationAbstractClass
      {
         [JsonProperty]
         private int m_baseInt;

         [JsonIgnore]
         public int BaseInt
         {
            get { return m_baseInt; }
            set { m_baseInt = value; }
         }
      }

      [Serializable]
      [JsonObject(MemberSerialization.OptIn)]
      public class Subclass1 : SerializationAbstractClass
      {
         [JsonProperty]
         private int m_subInt;

         [JsonIgnore]
         public int SubInt
         {
            get { return m_subInt; }
            set { m_subInt = value; }
         }
      }

 

      [Test]
      public void JsonSimpleTest()
      {
         TestSerializationSimpleClass testSerializationSimpleClass = GetTestSimpleClass();

         //serialize
         JsonSerializerMapper jsonSerializerMapper = new JsonSerializerMapper();
         Byte[] serializeBytes = jsonSerializerMapper.Serialize(testSerializationSimpleClass);

         //get a copy of the bytes
         serializeBytes = (Byte[])serializeBytes.Clone();

         //deserialize the bytes
         TestSerializationSimpleClass deserializedSerializationSimpleClass = (TestSerializationSimpleClass)jsonSerializerMapper.DeSerialize(serializeBytes, typeof(TestSerializationSimpleClass));

         Assert.AreEqual(testSerializationSimpleClass.DateTime.ToString(),deserializedSerializationSimpleClass.DateTime.ToString());
         Assert.AreEqual(testSerializationSimpleClass.Int, deserializedSerializationSimpleClass.Int);
         Assert.AreEqual(testSerializationSimpleClass.Double, deserializedSerializationSimpleClass.Double);
         Assert.AreEqual(testSerializationSimpleClass.String, deserializedSerializationSimpleClass.String);


         Assert.AreEqual(testSerializationSimpleClass.DoublesDicIntIndex.Count, deserializedSerializationSimpleClass.DoublesDicIntIndex.Count);
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(3));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.3));

         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(123));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1234));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1235));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1236));
      }

      [Test]
      public void JsonComplexTest()
      {
         TestSerializationComplexClass testSerializationComlexClass = GetTestComplexClass();

         //serialize
         JsonSerializerMapper jsonSerializerMapper = new JsonSerializerMapper();
         Byte[] serializeBytes = jsonSerializerMapper.Serialize(testSerializationComlexClass);

         //get a copy of the bytes
         serializeBytes = (Byte[])serializeBytes.Clone();

         //deserialize the bytes
         TestSerializationComplexClass deserializedSerializationSimpleClass = (TestSerializationComplexClass)jsonSerializerMapper.DeSerialize(serializeBytes, typeof(TestSerializationComplexClass));

         Assert.AreEqual(testSerializationComlexClass.DateTime.ToString(), deserializedSerializationSimpleClass.DateTime.ToString());
         Assert.AreEqual(testSerializationComlexClass.Int, deserializedSerializationSimpleClass.Int);
         Assert.AreEqual(testSerializationComlexClass.Double, deserializedSerializationSimpleClass.Double);
         Assert.AreEqual(testSerializationComlexClass.String, deserializedSerializationSimpleClass.String);


         Assert.AreEqual(testSerializationComlexClass.DoublesDicIntIndex.Count, deserializedSerializationSimpleClass.DoublesDicIntIndex.Count);
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(3));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.3));

         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(123));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1234));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1235));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1236));

         Assert.AreEqual(testSerializationComlexClass.DicTypeValue.Count, deserializedSerializationSimpleClass.DicTypeValue.Count);
         Assert.AreEqual(testSerializationComlexClass.DicListValue.Count, deserializedSerializationSimpleClass.DicListValue.Count);
         Assert.AreEqual(testSerializationComlexClass.DicClassValue.Count, deserializedSerializationSimpleClass.DicClassValue.Count);
         Assert.AreEqual(testSerializationComlexClass.Struct.Int1, deserializedSerializationSimpleClass.Struct.Int1);
         Assert.AreEqual(testSerializationComlexClass.Structs.Count, deserializedSerializationSimpleClass.Structs.Count);
         Assert.AreEqual(testSerializationComlexClass.AbstractList.Count, deserializedSerializationSimpleClass.AbstractList.Count);
      }

      [Test]
      public void JsonPerformanceTest()
      {
         IList<Byte[]> bytes = new List<byte[]>();

         TestSerializationSimpleClass testSerializationSimpleClass = GetTestSimpleClass();

         //serialize
         JsonSerializerMapper jsonSerializerMapper = new JsonSerializerMapper();

         Stopwatch sw = new Stopwatch();
         sw.Start();
         for (int i = 0; i < 2000; i++)
         {
            Byte[] serializeBytes = jsonSerializerMapper.Serialize(testSerializationSimpleClass);
            bytes.Add(serializeBytes);
         }
         sw.Stop();
         Console.WriteLine("Serialization Time: "+sw.Elapsed+"(ms)");


         //deserialize the bytes
         sw.Start();
         for (int i = 0; i < bytes.Count; i++)
         {
            TestSerializationSimpleClass deserializedSerializationSimpleClass = (TestSerializationSimpleClass)jsonSerializerMapper.DeSerialize(bytes[i], typeof(TestSerializationSimpleClass));  
         }
         sw.Stop();
         Console.WriteLine("DeSerialization Time: " + sw.Elapsed + "(ms)");


      }

      [Test]
      public void BinarySerializerSimpleTest()
      {
         TestSerializationSimpleClass testSerializationSimpleClass = GetTestSimpleClass();

         //serialize
         DefaultSerializerMapper jsonSerializerMapper = new DefaultSerializerMapper();
         Byte[] serializeBytes = jsonSerializerMapper.Serialize(testSerializationSimpleClass);

         //get a copy of the bytes
         serializeBytes = (Byte[])serializeBytes.Clone();

         //deserialize the bytes
         TestSerializationSimpleClass deserializedSerializationSimpleClass = (TestSerializationSimpleClass)jsonSerializerMapper.DeSerialize(serializeBytes, typeof(TestSerializationSimpleClass));

         Assert.AreEqual(testSerializationSimpleClass.DateTime.ToString(), deserializedSerializationSimpleClass.DateTime.ToString());
         Assert.AreEqual(testSerializationSimpleClass.Int, deserializedSerializationSimpleClass.Int);
         Assert.AreEqual(testSerializationSimpleClass.Double, deserializedSerializationSimpleClass.Double);
         Assert.AreEqual(testSerializationSimpleClass.String, deserializedSerializationSimpleClass.String);


         Assert.AreEqual(testSerializationSimpleClass.DoublesDicIntIndex.Count, deserializedSerializationSimpleClass.DoublesDicIntIndex.Count);
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(3));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.3));

         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(123));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1234));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1235));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1236));
      }

      [Test]
      public void BinarySerializerComplexTest()
      {
         TestSerializationComplexClass testSerializationComlexClass = GetTestComplexClass();

         //serialize
         DefaultSerializerMapper defaultSerializerMapper = new DefaultSerializerMapper();
         Byte[] serializeBytes = defaultSerializerMapper.Serialize(testSerializationComlexClass);

         //get a copy of the bytes
         serializeBytes = (Byte[])serializeBytes.Clone();

         //deserialize the bytes
         TestSerializationComplexClass deserializedSerializationSimpleClass = (TestSerializationComplexClass)defaultSerializerMapper.DeSerialize(serializeBytes, typeof(TestSerializationComplexClass));

         Assert.AreEqual(testSerializationComlexClass.DateTime.ToString(), deserializedSerializationSimpleClass.DateTime.ToString());
         Assert.AreEqual(testSerializationComlexClass.Int, deserializedSerializationSimpleClass.Int);
         Assert.AreEqual(testSerializationComlexClass.Double, deserializedSerializationSimpleClass.Double);
         Assert.AreEqual(testSerializationComlexClass.String, deserializedSerializationSimpleClass.String);


         Assert.AreEqual(testSerializationComlexClass.DoublesDicIntIndex.Count, deserializedSerializationSimpleClass.DoublesDicIntIndex.Count);
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.ContainsKey(3));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.1));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.2));
         Assert.IsTrue(deserializedSerializationSimpleClass.DoublesDicIntIndex.Values.Contains(1.3));

         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(123));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1234));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1235));
         Assert.IsTrue(deserializedSerializationSimpleClass.Doubles.Contains(1236));

         Assert.AreEqual(testSerializationComlexClass.DicTypeValue.Count, deserializedSerializationSimpleClass.DicTypeValue.Count);
         Assert.AreEqual(testSerializationComlexClass.DicListValue.Count, deserializedSerializationSimpleClass.DicListValue.Count);
         Assert.AreEqual(testSerializationComlexClass.DicClassValue.Count, deserializedSerializationSimpleClass.DicClassValue.Count);
         Assert.AreEqual(testSerializationComlexClass.Struct.Int1, deserializedSerializationSimpleClass.Struct.Int1);
         Assert.AreEqual(testSerializationComlexClass.Structs.Count, deserializedSerializationSimpleClass.Structs.Count);
         Assert.AreEqual(testSerializationComlexClass.AbstractList.Count, deserializedSerializationSimpleClass.AbstractList.Count);
      }


      [Test]
      public void BinarySerializerPerformanceTest()
      {
         IList<Byte[]> bytes = new List<byte[]>();

         TestSerializationSimpleClass testSerializationSimpleClass = GetTestSimpleClass();

         //serialize
         DefaultSerializerMapper serializerMapper = new DefaultSerializerMapper();

         Stopwatch sw = new Stopwatch();
         sw.Start();
         for (int i = 0; i < 2000; i++)
         {
            Byte[] serializeBytes = serializerMapper.Serialize(testSerializationSimpleClass);
            bytes.Add(serializeBytes);
         }
         sw.Stop();
         Console.WriteLine("Serialization Time: " + sw.Elapsed + "(ms)");


         //deserialize the bytes
         sw.Start();
         for (int i = 0; i < bytes.Count; i++)
         {
            TestSerializationSimpleClass deserializedSerializationSimpleClass = (TestSerializationSimpleClass)serializerMapper.DeSerialize(bytes[i], typeof(TestSerializationSimpleClass));
         }
         sw.Stop();
         Console.WriteLine("DeSerialization Time: " + sw.Elapsed + "(ms)");


      }

      private TestSerializationSimpleClass GetTestSimpleClass()
      {
         TestSerializationSimpleClass testSerializationSimpleClass = new TestSerializationSimpleClass();
         testSerializationSimpleClass.Int = 123;
         testSerializationSimpleClass.String = "abc";
         testSerializationSimpleClass.Double = Double.MaxValue;
         testSerializationSimpleClass.DateTime = DateTime.Now;
         testSerializationSimpleClass.Doubles.Add(123);
         testSerializationSimpleClass.Doubles.Add(1234);
         testSerializationSimpleClass.Doubles.Add(1235);
         testSerializationSimpleClass.Doubles.Add(1236);
         testSerializationSimpleClass.DoublesDicIntIndex.Add(1, 1.1);
         testSerializationSimpleClass.DoublesDicIntIndex.Add(2, 1.2);
         testSerializationSimpleClass.DoublesDicIntIndex.Add(3, 1.3);


         return testSerializationSimpleClass;
      }

      private TestSerializationComplexClass GetTestComplexClass()
      {
         TestSerializationComplexClass testSerializationComplexClass = new TestSerializationComplexClass();
         testSerializationComplexClass.Int = 123;
         testSerializationComplexClass.String = "abc";
         testSerializationComplexClass.Double = Double.MaxValue;
         testSerializationComplexClass.Doubles.Add(123);
         testSerializationComplexClass.Doubles.Add(1234);
         testSerializationComplexClass.Doubles.Add(1235);
         testSerializationComplexClass.Doubles.Add(1236);
         testSerializationComplexClass.DoublesDicIntIndex.Add(1, 1.1);
         testSerializationComplexClass.DoublesDicIntIndex.Add(2, 1.2);
         testSerializationComplexClass.DoublesDicIntIndex.Add(3, 1.3);

         TestSerializationComplexClass t3 = new TestSerializationComplexClass();
         t3.Int = 999;
         testSerializationComplexClass.DicClassValue.Add(1, t3);
         testSerializationComplexClass.DicClassValue.Add(2, t3);
         testSerializationComplexClass.DicClassValue.Add(3, t3);

         List<TestSerializationComplexClass> list1 = new List<TestSerializationComplexClass>();
         list1.Add(new TestSerializationComplexClass());
         list1.Add(new TestSerializationComplexClass());
         list1.Add(new TestSerializationComplexClass());

         ClassStruct tStruct = new ClassStruct();
         tStruct.Int1 = 123;
         testSerializationComplexClass.Struct = tStruct;


         testSerializationComplexClass.DicListValue.Add(1, list1);

         TestSerializationComplexClass ta1 = new TestSerializationComplexClass();
         ta1.Int = 123;
         TestSerializationComplexClass ta2 = new TestSerializationComplexClass();
         ta2.Int = 456;
         TestSerializationComplexClass ta3 = new TestSerializationComplexClass();
         ta3.Int = 790;


         testSerializationComplexClass.DicClassIndex.Add(ta1, 1);
         testSerializationComplexClass.DicClassIndex.Add(ta2, 2);
         testSerializationComplexClass.DicClassIndex.Add(ta3, 3);

         testSerializationComplexClass.Types.Add(typeof(TestSerializationComplexClass));
         testSerializationComplexClass.DicTypeValue.Add("test", typeof(TestSerializationComplexClass));
         testSerializationComplexClass.DicTypeValue.Add("type1", typeof(TestSerializationComplexClass));


         testSerializationComplexClass.Structs.Add("one", new ClassStruct());
         testSerializationComplexClass.Structs.Add("two", new ClassStruct());
         testSerializationComplexClass.AbstractList.Add(new Subclass1());

         return testSerializationComplexClass;
      }

   /// <summary>
   ///
   /// </summary>
   public interface ISerializer
   {
      /// <summary>
      /// Serializes the specified object data.
      /// </summary>
      /// <param name="objectData">The object data.</param>
      /// <returns></returns>
      byte[] Serialize(object objectData);

      /// <summary>
      /// Des the serialize.
      /// </summary>
      /// <param name="objectData">The object data.</param>
      /// <returns></returns>
      object DeSerialize(byte[] objectData,Type objectType);

      /// <summary>
      /// Inits this instance.
      /// </summary>
      void Init();
   }

   /// <summary>
   ///
   /// </summary>
   public class JsonSerializerMapper : ISerializer
   {

      #region IMapSerializer Members
      /// <summary>
      /// Serializes the specified object data.
      /// </summary>
      /// <param name="objectData">The object data.</param>
      /// <returns></returns>
      public byte[] Serialize(object objectData)
      {

         if (objectData == null)
            return null;

         MemoryStream memoryStream = new MemoryStream();

         JsonSerializer jsonSerializer = new JsonSerializer();
         jsonSerializer.Converters.Add(new TypeConverter());
        
         BsonWriter bsonWriter = new BsonWriter(memoryStream);
         jsonSerializer.Serialize(bsonWriter, objectData);

         return memoryStream.GetBuffer();
      }


      /// <summary>
      /// Deserializes the given bytes into an object.
      /// </summary>
      /// <param name="objectData">The object data.</param>
      /// <param name="objectType"></param>
      /// <returns></returns>
      public object DeSerialize(byte[] objectData, Type objectType)
      {
         if (objectData != null)
         {
            MemoryStream memoryStream = new MemoryStream(objectData);

            JsonSerializer jsonSerializer = new JsonSerializer();
            jsonSerializer.Converters.Add(new TypeConverter());

            BsonReader bsonReader = new BsonReader(memoryStream);

            return jsonSerializer.Deserialize(bsonReader, objectType);
         }

         return null;
      }


      /// <summary>
      /// Inits this instance.
      /// </summary>
      public void Init()
      {
      }
      #endregion
   }

   /// <summary>
   /// Converts a Type value to and from a string value.
   /// </summary>
   public class TypeConverter : JsonConverter
   {
      /// <summary>
      /// Writes the JSON representation of the object.
      /// </summary>
      /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
      /// <param name="value">The value.</param>
      /// <param name="serializer">The calling serializer.</param>
      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
      {
         if (value == null)
         {
            writer.WriteNull();
            return;
         }

         writer.WriteValue(((Type)value).FullName + ", " + ((Type)value).Assembly.GetName().Name);
      }

      /// <summary>
      /// Reads the JSON representation of the Type object.
      /// </summary>
      /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
      /// <param name="objectType">Type of the object.</param>
      /// <param name="serializer">The calling serializer.</param>
      /// <returns>The object value.</returns>
      public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
      {
         if (reader.TokenType == JsonToken.Null)
            return null;

         string encodedData = reader.Value.ToString();
         if (encodedData.Length > 0)
            return Type.GetType(encodedData);

         return null;
      }

      /// <summary>
      /// Determines whether this instance can convert the specified object type.
      /// </summary>
      /// <param name="objectType">Type of the object.</param>
      /// <returns>
      ///  <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
      /// </returns>
      public override bool CanConvert(Type objectType)
      {
         if (objectType.IsAssignableFrom(typeof(Type).GetType()))
            return true;

         return false;
      }
   }

   /// <summary>
   ///
   /// </summary>
   public class BinarySerializer : ISerializer
   {

      #region IMapSerializer Members

      /// <summary>
      /// Serializes the specified object data.
      /// </summary>
      /// <param name="objectData">The object data.</param>
      /// <returns></returns>
      public byte[] Serialize(object objectData)
      {
         if (objectData == null)
         {
            return null;
         }
         else
         {
            using (MemoryStream memoryStream = new MemoryStream())
            {
               BinaryFormatter binaryFormatter = new BinaryFormatter();
               binaryFormatter.Serialize(memoryStream, objectData);
               return memoryStream.ToArray();
            }
         }
      }

      /// <summary>
      /// Deserializes the given bytes into an object.
      /// </summary>
      /// <param name="objectData">The object data.</param>
      /// <param name="objectType"></param>
      /// <returns></returns>
      public object DeSerialize(byte[] objectData,Type objectType)
      {
         if (objectData != null)
         {
            using (MemoryStream memoryStream = new MemoryStream(objectData))
            {
               BinaryFormatter binaryFormatter = new BinaryFormatter();
               return binaryFormatter.Deserialize(memoryStream);
            }
         }
         else
         {
            return null;
         }
      }

      /// <summary>
      /// Inits this instance.
      /// </summary>
      public void Init()
      {
      }
      #endregion
   }

}

Coordinator
Feb 2, 2010 at 9:33 AM
Edited Feb 2, 2010 at 9:35 AM

Remember to test under release mode, otherwise you're comparing a debug Json.NET dll against a release .NET framework one.

I found serializing faster in Json.NET and deserializing slower - however I did a quick profile and made a small change to the deserializer to speed it up by 50%. There was a case where I hadn't applied an earlier optimization around caching the creation of generic types. There are a couple of things I could do to speed up serializing as well but they are more work and I'll leave them to after some other work I want to do.

Note that I removed the JsonConverter since that functionality is now built into Json.NET. Having type converters slows down Json.NET a bit since it has to test every type before it serializes it whether there is a valid converter.

To get the complex test to pass you need a TypeConverter. Json.NET needs to know how to convert the class to a string and back again when it is a dictionary key.

Feb 2, 2010 at 4:19 PM

Ill also try it in release mode but with the dictionary key , couldnt it check to see if string can be retrieved through json(implements the json attribute) , if it can then it could just run it through json. Just a thought to make it more automatic.

 

thanks

 

scott

Coordinator
Feb 2, 2010 at 10:21 PM
Edited Feb 21, 2010 at 8:04 AM

The key can only be a simple string.

{
  "I'm the key":"value"
}

The serializer automatically attempts to convert the key object to a string but if that fails it would have to be serialized to a complex object which wouldn't be valid JSON.

{
  {"This is not valid JSON":1}:"value"
}

And I don't want to have an escaped JSON object in the string as the dictionary key.

 

To get this scenario to work you need to implement a TypeConverter so Json.NET knows how to convert an object to a string and back again. Kapeesh?

Feb 21, 2010 at 5:57 AM
Edited Feb 21, 2010 at 6:27 AM

What about simple strings containing a backslash (reverse solidus)? Would it not be appropriate to escape these?

E.g. a key of "user\domain" becomes "user\\domain". Currently it is not expanded.

 

 

Feb 21, 2010 at 6:26 AM

In particular, I'm suggesting that

JsonTextWriter.WritePropertyName
should call
JavaScriptUtils.WriteEscapedJavaScriptString(_writer, name, _quoteChar, false);

rather than

_writer.Write(name);

 

A test to show what I mean (right now, the final assertion fails):

      [Test]
      public void TestEscapeDictionaryStrings()
      {
          const string s = @"host\user";
          string serialized = JsonConvert.SerializeObject(s);
          Assert.That(serialized, Is.EqualTo(@"""host\\user"""));

          Dictionary<int, object> d1 = new Dictionary<int, object>();
          d1.Add(5, s);
          Assert.That(JsonConvert.SerializeObject(d1), Is.EqualTo(@"{""5"":""host\\user""}"));

          Dictionary<string, object> d2 = new Dictionary<string, object>();
          d2.Add(s, 5);
          Assert.That(JsonConvert.SerializeObject(d2), Is.EqualTo(@"{""host\\user"":5}"));
      }

Does that make sense?

 

 

Coordinator
Feb 21, 2010 at 10:01 AM

Good find. Now fixed in the latest version of the source code.

http://json.codeplex.com/SourceControl/list/changesets