[Free] MessagePack (binary) and Json (text) serialization

MessagePack and Json serialization package allow you to save/load your data into/from file or network stream.

[Source Code]
[Documentation] [Package In Asset Store]

Supported Platforms:

• PC/Mac/Linux
• IOS
• Android
• WebGL

Serialized types:

• Primitives: Boolean, Byte, Double, Int16, Int32, Int64, SBytes, Single, UInt16, UInt32, UInt64, String
• Standart Types: Decimal, DateTimeOffset, DateTime, TimeSpan, Guid, Uri, Version, DictionaryEntry
Unity3D Types: Bounds, Vector, Matrix4x4, Quaternion, Rect, Color
• Binary: Stream, byte[ ]
• Lists: Array, ArrayList, List[T], HashSet[T] and any other IEnumerable types with Add method
• Maps: Hashtable, Dictionary[K,V], and other IDictionary types
• Nullable types
• Enumeration
• Objects

2 Likes

There’s a bug in the current version (1.0.10) related to serializing null values in arrays because it doesn’t call WriteFormatting() in the WriteNull() function.

I fixed this bug. The new version on GitHub and will soon be in Asset Store.
Thank you for such a detailed error report.

Great job!

May i post here some feedback?

  1. it would be nice to have some Exception in case of trying to deserialize stream which Position != 0. First of all i tried to serialize and deserialize some object just from that MemoryStream and it took me some time to get that stream must be in zero position to deserialization work.
  2. Example in documentation is simple but not actually helpful. RectSerializer code seems more useful.
  3. I can’t get how it is designed to serialize MemoryStream properly.
    I have a code like this:
public MemoryStream gameRoomData;
......       
writer.WriteMember("g");
writer.WriteValue(src.gameRoomData, typeof(MemoryStream));
writer.WriteObjectEnd();

Trying to execute it generates Exception:

The only way i could find to make it work was this hack in JsonWriterExtentions.cs:

            var actualValueType = value.GetType();
//dirty hack start
            if (valueType == typeof(System.IO.MemoryStream))
            {
                actualValueType = typeof(System.IO.Stream);
            }
//dirty hack end
            var serializer = writer.Context.GetSerializerForType(actualValueType);

What do i do wrong?

  1. Currently it’s throwing “Unexpected token ‘EndOfStream’” it’s quite descriptive.
  2. Yep, description is quite short. It’s hard for me writing documentation in english.
  3. I make few changed related to Stream serialization in source code on GitHub, but your code still will not work without changes. It’s throws exception because it’s don’t know how to serialize MemoryStream, only Stream(base class of MemoryStream) and you should:
    a) use WriteValue(memoryStream, typeof(Stream))
    b) use class with Stream property/field
    c) make hint to serializer how to serialize MemoryStream
    class Program
    {
        public class MyClass
        {
            public MemoryStream mySteam;
        }
        public static void Main()
        {
            // prepare context
            var context = new SerializationContext
            {
                Serializers = { { typeof(MemoryStream), StreamSerializer.Instance } },
                // or
                SerializerFactory = type => (type == typeof(MemoryStream)) ? StreamSerializer.Instance : null,
                // this will suppress _type member
                Options = SerializationOptions.SuppressTypeInformation
            };

            var myObject = new MyClass
            {
                mySteam = new MemoryStream(...)
            };
            var tmpStream = new MemoryStream();
            MsgPack.Serialize(myObject, tmpStream, context);

            // reading MyClass
            tmpStream.Position = 0;
            myObject = MsgPack.Deserialize<MyClass>(tmpStream, context);

            // reading MyClass manually
            tmpStream.Position = 0;
            var reader = new MsgPackReader(tmpStream, context);

            reader.ReadObjectBegin();
            if (reader.ReadMember() != "mySteam") throw JsonSerializationException.UnexpectedMemberName(reader.Value.AsString, "mySteam", reader);
            var readedStream = (MemoryStream)reader.ReadValue(typeof(MemoryStream));
            reader.ReadObjectEnd(nextToken: false);
        }
    }

And you should’t write custom TypeSerializers for your classes if they too complex for serialization. It’s better to declare “data storage” class and put all data into it. Writing custom TypeSerializer is quite advanced solution.

1 Like

Thank you for reply!

Is there any way to get serialisation working with generics? Can I attach a TypeSerializer to a generic class?

Could you provide some example of class (c# code) which you want to serialize?

1 Like

Hi, i’m new to unity, i used binary formater to do save and load before. then after learned a bit about other method to save and load, i found option like bf (ofcourse), json (the readable ones), and msgpack (the smallest ones). if you don’t mind, can you give me example (complete ones) on save() and load() function in unity using persistentdatapath and msgpack please… thanks a lot.

Hi!

You could ‘save’ and ‘load’ any custom class with following code:

        [DataContract]
        public class MySaveClass
        {
            [DataMember]
            public int MyField;
        }

        public static void Save(MySaveClass mySaveClass)
        {
            using (var saveFile = System.IO.File.Create(System.IO.Path.Combine(Application.persistentDataPath, "my.save")))
            {
                MsgPack.Serialize(mySaveClass, saveFile, SerializationOptions.None);
            }
        }
        public static MySaveClass Load()
        {
            using (var saveFile = System.IO.File.OpenRead(System.IO.Path.Combine(Application.persistentDataPath, "my.save")))
            {
                return MsgPack.Deserialize<MySaveClass>(saveFile, SerializationOptions.None);
            }
        }

Of course checks for arguments, paths and file existence are required. This is scaffold code.

Hi @DenisZykov
When import to Unity 2018.3.0f2, its throw below error:

Assets\Plugins\GameDevWare.Serialization\Metadata\ReflectionUtils.cs(86,34): error CS0246: The type or namespace name 'DynamicMethod' could not be found (are you missing a using directive or an assembly reference?)

Unity 2018.3.0f2 which default script runtime version is .NET 4.x, and SRV .NET 3.5.x was deprecated, so will be remove in the future. Please fix this ! Thanks in advanced

1 Like

@DenisZykov Please provide a updated sample how to use your library with data comes from e.g. WebSocket ?
Thank you very much.