Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protobuf-net enum backwards compatibility

I was trying to add a new enum value for a certain protobuf-serialized class in a new app version, and while testing, noticed that the previous version will throw an exception, given this new file format:

An unhandled exception of type 'ProtoBuf.ProtoException' occurred in protobuf-net.dll
Additional information: No {enum-type-name} enum is mapped to the wire-value 3

It is fairly obvious that it's telling me that there is no enum value for the int value of 3, but I always had the idea that Protocol Buffers defaulted to the zero-valued ("default") enum value (if such exists), in case that an actual enum value couldn't be mapped to.

To clarify, this can be reproduced using the following example (I am intentionally doing the deserialization step into a different class to mimic old app trying to load the new format):

// --- version 1 ---

public enum EnumV1
{
    Default = 0,
    One = 1,
    Two = 2
}

[ProtoContract]
public class ClassV1
{
    [ProtoMember(1)]
    public EnumV1 Value { get; set; }
}



// --- version 2 ---

public enum EnumV2
{
    Default = 0,
    One = 1,
    Two = 2,
    Three = 3 // <- newly added
}

[ProtoContract]
public class ClassV2
{
    [ProtoMember(1)]
    public EnumV2 Value { get; set; }
}

And the following code will fail:

// serialize v2 using the new app
var v2 = new ClassV2() { Value = EnumV2.Three };
var v2data = Serialize(v2);

// try to deserialize this inside the old app to v1
var v1roundtrip = Deserialize<ClassV1>(v2data);

Since v1 is out in the open, is there some metadata I can use when serializing in v2 to avoid this issue? I can, of course, get myself out of this trouble by rewriting v2 to use a separate property and leave the enum values unmodified, but I'd like to make enums backwards compatible if possible.

like image 926
Groo Avatar asked Feb 24 '16 11:02

Groo


1 Answers

Adding [ProtoContract(EnumPassthru=true)] to your enums will allow protobuf-net to deserialize unknown values.

Unfortunately, there is no way to retroactively fix your v1. You'll have to use a different property.

like image 171
yaakov Avatar answered Oct 11 '22 17:10

yaakov