浏览代码

Oneof field should be serialized even it's equal to default. (#3153)

Paul Yang 8 年之前
父节点
当前提交
c344fe8caa

+ 3 - 1
php/ext/google/protobuf/encode_decode.c

@@ -1167,6 +1167,7 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
        upb_msg_field_next(&i)) {
     upb_fielddef* f = upb_msg_iter_field(&i);
     uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
+    bool containing_oneof = false;
 
     if (upb_fielddef_containingoneof(f)) {
       uint32_t oneof_case_offset =
@@ -1179,6 +1180,7 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
       }
       // Otherwise, fall through to the appropriate singular-field handler
       // below.
+      containing_oneof = true;
     }
 
     if (is_map_field(f)) {
@@ -1209,7 +1211,7 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
 #define T(upbtypeconst, upbtype, ctype, default_value)     \
   case upbtypeconst: {                                     \
     ctype value = DEREF(message_data(msg), offset, ctype); \
-    if (value != default_value) {                          \
+    if (containing_oneof || value != default_value) {      \
       upb_sink_put##upbtype(sink, sel, value);             \
     }                                                      \
   } break;

+ 7 - 0
php/src/Google/Protobuf/Internal/Message.php

@@ -739,6 +739,13 @@ class Message
      */
     private function existField($field)
     {
+        $oneof_index = $field->getOneofIndex();
+        if ($oneof_index !== -1) {
+            $oneof = $this->desc->getOneofDecl()[$oneof_index];
+            $oneof_name = $oneof->getName();
+            return $this->$oneof_name->getNumber() === $field->getNumber();
+        }
+
         $getter = $field->getGetter();
         $value = $this->$getter();
         return $value !== $this->defaultValue($field);

+ 7 - 0
php/tests/encode_decode_test.php

@@ -88,6 +88,13 @@ class EncodeDecodeTest extends TestBase
         $n = new TestMessage();
         $n->mergeFromString($data);
         $this->assertSame(1, $n->getOneofMessage()->getA());
+
+        // Encode default value
+        $m->setOneofEnum(TestEnum::ZERO);
+        $data = $m->serializeToString();
+        $n = new TestMessage();
+        $n->mergeFromString($data);
+        $this->assertSame("oneof_enum", $n->getMyOneof());
     }
 
     public function testPackedEncode()