MessagePack polymorphism issue

Hi,
I am using MsgPack for serializing and deserializing data and have encountered an issue.
I have a base abstract class called Item, which contains some properties that all items share. And then I have different types of items, like Weapon, Armor and etc… Which have type specific properties.

The problem is that when I serialize the array of items (Item[ ]) it only serializes item class properties, but it doesn’t serialize the properties from the class that inherits the base class.

What is the solution to this?

[MessagePackObject]
public abstract class Item
{
    [Key(1)]
    public int id = 0;
    [Key(2)]
    public string name = "";
    [Key(3)]
    public string icon = "";
    [Key(4)]
    public int maxValue = 1;
    [Key(5)]
    public bool isStackable = true;
}
[MessagePackObject]
public class Weapon : Item
{
    [Key(1)]
    public float damage = 4;
    [Key(2)]
    public float reload = 1;
    [Key(3)]
    public float recoil = 2;
    [Key(4)]
    public float weight = 4;
    [Key(5)]
    public float melee = 3;
}
[MessagePackObject]
public class Armor : Item
{
    [Key(1)]
    public float strength = 14;
}

Item[] items = new Item[4]
{
    new Weapon(),
    new Armor(),
    new Weapon(),
    new Weapon()
};

public void Save()
{
    var data = MessagePackSerializer.Serialize(items);

    var path = ItemDatabase.Path;

    if (!File.Exists(path))
    {
        File.Create(path).Close();
    }
    File.WriteAllText(path, MessagePackSerializer.ConvertToJson(data));
}

Is it because you’re recycling key numbers? Disclaimer: have no idea wtf this msg-thingy is.

2 Likes

I was looking for fast serialization and I stumbled upon this on GitHub. Apparently it’s mega fast, faster than Protobuf. So I decided to give it a go and it works great and it is really easy to setup in Unity, just download the package, all well except for this issue. I’m not sure about the keys. I tried putting them in order, then removing them, but still the same issue

I think you’re supposed to use Union for abstract classes. Check their readme:

https://github.com/neuecc/MessagePack-CSharp#union

1 Like

I think it works now! I just added
[MessagePack.Union(0, typeof(Weapon))]
[MessagePack.Union(1, typeof(Armor))]

above item class and it now serializes all properties! So I suppose you have to put all possible inheritance types?

p.s. Also had to make sure that all keys are unique in all classes. It gave me an error otherwise

I think I will just stick with JSON. :slight_smile:

Ye, I am still having issue with it, it deserializes the data wrong. :face_with_spiral_eyes: In the file it clearly says that the name is “Item” for e.g. but after it deserializes it results in empty string. Really confused… The only reason I decided to use this is because I need to load a mega huge database that could contain dozen on items with many properties. Json is fast, but not sure how would it perform when dealing with such task. I might try Utf8Json I heard it’s also pretty fast. Might be easier to be honest

If you look in the programmers dictionary under “Speculative optimization,” the above paragraph is what you’ll find.

JSON is used heavily by the whole world in highly performant large scale production environments. Think Twitter. Think Facebook. Think millions of users blasting records back and forth nonstop.

I highly doubt that across the board JSON would be outperformed by some other thing I’ve never heard of. I’m open to the possibility for sure, but since JSON is a) highly cross platform supported, b) as performant as I’ve ever needed, and c) does the job, well, I’d never reach for anything else.

Mega huge with dozens of many?? I don’t think that is quite as mega huge as you believe it to be.

When you do reach for JSON, go to the asset store and get JSON .NET because a) it is free, and b) it is fully-featured, as compared with Unity’s built in “tiny micro JSON” implementation, which is NOT fully featured.

Yeah I do like Json it’s great, I’ve used it in many projects, although I kinda like this as well. I actually figured it out I think. The reason the deserializer gave incorrect results was because I needed to provide same resolver as the one I used for the serializer. As it allowed privates to be serialized, so same had to be done when deserializing. But yeah now it works great! I will be using Json, but in some other places. I’ll do some testing, if I don’t run into any mayor issues, I’ll probably stick with this serializer for this purpose.

1 Like