pizheng / protobuf-net

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

Optional fields with default value are not serialized even when explicitly set. #136

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Please include an e-mail address if this might need a dialogue!
==============

What steps will reproduce the problem?
1. Create a message with an optional field, say MyField.
2. Explicitly assign default value to the field or set MyFieldSpecified 
property to true.
3. Serialize the message.
4. Deserialize the message.

What is the expected output?
1. The serialized message should have the field serialized.
2. Deserialized object should have MyFieldSpecified set to true.

What do you see instead?
1. The field is skipped during serialization.
2. Deserialized object should have my_fieldSpecified set to true.

What version of the product are you using? On what operating system?
rev. 357 (v2)

Please provide any additional information below.

This issue could possibly be related to 
http://stackoverflow.com/questions/2810295/serialization-of-non-required-fields-
in-protobuf-net

Files that demonstrated the problem attached as well as a patch that resolves 
the problem.

Alexandre Kozlov
alexandre.kozlov@gmail.com

Original issue reported on code.google.com by alexandr...@gmail.com on 24 Oct 2010 at 9:07

Attachments:

GoogleCodeExporter commented 9 years ago
even worse:

using System.IO;
using ProtoBuf;

namespace protobufnetTest
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Console.WriteLine ("Hello World!");
            var pt = new PTest() { Tint = 0 };

            var ms = new MemoryStream();
            ProtoBuf.Serializer.Serialize<PTest>(ms, pt);
            ms.Seek (0, SeekOrigin.Begin);
            var pt2 = ProtoBuf.Serializer.Deserialize<PTest>(ms);

//          Console.WriteLine ("pt2 hasValue: " + pt2.Tint.HasValue);
//          Console.WriteLine ("pt2 Value: " + pt2.Tint.Value);
//          System.Diagnostics.Debug.Assert(pt2.Tint.Value == pt.Tint.Value, 
"Different!!");

            Console.WriteLine ("pt2 hasValue: " + pt2.TintSpecified);
            Console.WriteLine ("pt2 Value: " + pt2.Tint);
            System.Diagnostics.Debug.Assert(pt2.Tint == pt.Tint, "Different!!");
            if (pt2.Tint != pt.Tint) Console.WriteLine("Different!!");
        }
    }

    [ProtoBuf.ProtoContract]
    public class PTest {
//      [ProtoBuf.ProtoMember(1)]
//      public int? Tint {get; set;}

        private int? tint;

        [ProtoMember(1)]
        public int Tint
        {
            get { return tint ?? 5; }
            set { tint = value;}
        }

        public bool TintSpecified
        {
            get { return tint != null; }
            set { if(value == (tint == null)) tint = value ? Tint : (int?)null;}
        }

        private bool ShouldSerializeTint() {return TintSpecified; }
        private void ResetTint() { TintSpecified = false; }

    }
}

Original comment by agustin....@gmail.com on 1 Oct 2011 at 10:13

GoogleCodeExporter commented 9 years ago
:( This really is a problem. Another very simple attached example.
I'm not certain the patch fixes the issue at my end

Original comment by fasd...@gmail.com on 3 Nov 2011 at 11:44

Attachments:

GoogleCodeExporter commented 9 years ago
I believe the original patch from the bug submitter correctly fixes the issue. 
I would very much appreciate it if the patch could be applied, it is causing my 
rpc library http://code.google.com/p/protobuf-remote/ to fail when used with v2.

Also I think comment #2 is incorrect, it shows the expected behavior. It should 
instead be using the DefaultValue attribute to set the field to true.

Original comment by niallr...@gmail.com on 31 Mar 2012 at 3:56

GoogleCodeExporter commented 9 years ago
Any hope of seeing this fix in an official build?
This issue is causing us a lot of trouble, as we're trying to have a Java 
back-end communicate with a C# front-end, and the Protobuf serialization on the 
Java end handles this use case properly.

Original comment by ndeslan...@live.fr on 20 Mar 2013 at 11:59

GoogleCodeExporter commented 9 years ago
Hi, 

do you have any plans/updates for the issue?

Example below shows that you can get wrong value not just wrong specified 
property. 

Have message TestMessage {
    optional int32 intField = 1 [default = -1];  // Override int default
}

Generate code with protogen -p:detectMissing

Run unit test below

[Test]
public void SerializeZero()
{
    var message = new TestMessage {intField = 0};  // Set int default

    TestMessage deserialized;
    byte[] data;

    using (var stream = new MemoryStream())
    { 
        Serializer.Serialize(stream, message); 
        data = stream.ToArray(); 
    }

    using (var stream = new MemoryStream(data))
    { deserialized = Serializer.Deserialize<TestMessage>(stream); }

    Assert.AreEqual(0, deserialized.intField);
    Assert.True(deserialized.intFieldSpecified);
}

What is the expected output? What do you see instead?

deserialized.intField should be 0, deserialized.intFieldSpecified should be true
I see deserialized.intField is -1, deserialized.intFieldSpecified is false

What version of the product are you using? 
both 2.0.0.622, 1.0.0.280

Original comment by katy.boc...@gmail.com on 10 Apr 2013 at 11:10