DeSerialization issue with Dictionary

Hey all,

I’m stuck on a strange serialization issue.

I’m trying to convert Byte array to object, I have Dictionary in that class. When trying to Deserialize it always throwing Serialization error.

Receiving serialization issue when the dictionary is null or dictionary count is 0. Am not receiving any serialization error When the dictionary have atleast one record. if any one faced this before let me know how to resolve this issue.

here is the method am using to Deserialize.

public static object ByteArrayToObject(this byte[] arrBytes)
	{
		if(arrBytes == null)
			return null;

		MemoryStream memStream = new MemoryStream();
		BinaryFormatter binForm = new BinaryFormatter();
		memStream.Write(arrBytes, 0, arrBytes.Length);
		memStream.Seek(0, SeekOrigin.Begin);
		object obj = (object)binForm.Deserialize(memStream);
		return obj;
	}

Error - Stream Reading : System.Runtime.Serialization.SerializationException: No element named KeyValuePairs could be found.
  at System.Runtime.Serialization.SerializationInfo.GetValue (System.String name, System.Type type) [0x00033] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Runtime.Serialization/SerializationInfo.cs:144 
  at System.Collections.Generic.Dictionary`2[System.String,System.String].OnDeserialization (System.Object sender) [0x00058] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:517 
  at System.Runtime.Serialization.ObjectManager.RaiseDeserializationEvent () [0x00075] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Runtime.Serialization/ObjectManager.cs:169 
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (System.IO.BinaryReader reader) [0x0001a] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:147 
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (BinaryElement elem, System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) [0x0003f] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:110 
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) [0x00078] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:179 
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) [0x00000] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:136 

Thanks.

ok this is happening because your casting to an object rather than the actual type. The method has no way of telling whether a null should be an empty collection or not and a null value is just a null value pure and simple. After some testing I come up with the following code which runs without error and handles null for any type.
Note I used Generics to make it more robust as Generics will tell you the type you need rather than having to determine the type from an object:

    public static byte[] ObjectToByteArray<T>(this T obj)
    {
        MemoryStream m = new MemoryStream();
        if (obj != null)
        {
            BinaryFormatter b = new BinaryFormatter();

            b.Serialize(m, obj);
        }
        return m.ToArray();
    }
    public static T ByteArrayToObject<T>(this byte[] arrBytes)
    {
        if (arrBytes == null || arrBytes.Length < 1)
            return default(T);

        BinaryFormatter binForm = new BinaryFormatter();

        T obj = (T)binForm.Deserialize(new MemoryStream(arrBytes));

        return obj;
    }

Tested with the following code:

        Dictionary<string, int> a = new Dictionary<string, int>();
        Dictionary<int, string> b = null;

        byte[] ba = a.ObjectToByteArray();
        Debug.Log(ba.Length);

        a = ba.ByteArrayToObject<Dictionary<string, int>>();

        ba = b.ObjectToByteArray();
        b = ba.ByteArrayToObject <Dictionary<int, string>>();
        Debug.Log(ba.Length);

You can opt for much simpler way to serialise gameplay data with the help of our new plugin Runtime Serialization for Unity. For more info please check our official thread.