From 1e86ef4e9f0b9c9e8bd8d62a61e141f139366920 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Mon, 29 May 2017 22:04:20 -0700 Subject: [PATCH] Oneof field should be serialized even it's equal to default. (#3153) --- php/ext/google/protobuf/encode_decode.c | 4 +++- php/src/Google/Protobuf/Internal/Message.php | 7 +++++++ php/tests/encode_decode_test.php | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c index 28bf18f4d5..6e3c606b6c 100644 --- a/php/ext/google/protobuf/encode_decode.c +++ b/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; diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index cd15e0f042..10c639ac2c 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/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); diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php index 288df5696d..b4cfed422b 100644 --- a/php/tests/encode_decode_test.php +++ b/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()