pizheng / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

.Proto - Enum without default value not correctly serialized #216

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Using following proto definition:

message Message {
    required uint32 messageId = 1;
    enum Type {
        IDENTIFICATION = 1;
        TYPE1 = 2;
        TYPE2 = 3;
        TYPE3 = 4;
    }
    optional Type command = 2;
    optional bytes realMessage = 3;
}

- Generate by protc definition for java and create server in java
- Create c# implementation by using protogen with default options
- Create simple sending example in C#

TcpClient client = new TcpClient();
            IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7000);
            client.Connect(serverEndPoint);
            NetworkStream clientStream = client.GetStream();

            var message = Message
            {
                messageId = 2,
                command = Message.Type.IDENTIFICATION,
            };

            var ms = new MemoryStream();
            Serializer.Serialize<Message>(ms, message);

            byte[] buffer = ms2.ToArray();

            clientStream.Write(buffer, 0 , buffer.Length);
            clientStream.Flush();
            clientStream.Close();

- send it to java server

ERROR:
- the first value from the enum is not serialized properly eg. when i use code 
above the buffer array is two byte length [8 2]. But when I use java to create 
the same message (from the same proto file) i got four bytes [8 2 16 1]. The 
same is when I try to serialize message with next enum value eg. Type.Type1 
will create correct serialized array [8 2 16 2]. 

SOLUTION:
- the problem dissapear when i assign default value to the message type eg. 

message Message {
    required uint32 messageId = 1;
    enum Type {
        IDENTIFICATION = 1;
        TYPE1 = 2;
        TYPE2 = 3;
        TYPE3 = 4;
    }
    optional Type command = 2 [ default = IDENTIFICATION ];
    optional bytes realMessage = 3;
}

but for the first time user it can be problematic. Either correct this error or 
give message when creating implementation from .proto file using protogen

Original issue reported on code.google.com by slawek.m...@gmail.com on 7 Aug 2011 at 10:51

GoogleCodeExporter commented 9 years ago
Interesting. The implicit default value is (by protobuf rules) the first enum 
value (IDENTIFICATION), so this is odd; I wonder if the existing detectMissing 
switch might help? 

Original comment by marc.gravell on 8 Aug 2011 at 10:04

GoogleCodeExporter commented 9 years ago
I have similar situation (C#). 
Have very simple enum and class:

    [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
    public class FullVehicleDummy : VehicleDummy
    {
        private ConnectionState connectionState = ConnectionState.Disconnected;

        [DefaultValue(ConnectionState.Disconnected)]
        public ConnectionState ConnectionState
        {
            get { return connectionState; }
            set { connectionState = value; }
        }
    }

    public enum ConnectionState
    {
        Connected,
        Disconnected,
        SuperConected,
        NotConected
    }

ConnectionState property works well only with DefaultValue attribute. In other 
case it seems that protobuf doesn't serialize/deserialize it properly. 
Used 2.0.0.621 version of protobuf-net.dll.

Original comment by aldoshki...@gmail.com on 26 Sep 2013 at 12:27

GoogleCodeExporter commented 9 years ago
Yes, noted. This is the implicit zero default behaviour. If I was designing the 
library from scratch, I probably would have made this work differently. As it 
is currently, to preserve backwards compatibility, you can change this *for 
custom models*, by setting

    model.UseImplicitZeroDefaults = false;

(and using that model rather than Serializer.Serialize / Serializer.Deserialize)

Alternatively, you can use [DefaultValue(...)] (as noted), or (when a 
[ProtoMember] is present): IsRequired=true

Original comment by marc.gravell on 26 Sep 2013 at 12:47

GoogleCodeExporter commented 9 years ago
Marc, thank you for quick answer, will use your advice.

Original comment by aldoshki...@gmail.com on 26 Sep 2013 at 12:53