diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c index e4b3566b52..17233275b8 100644 --- a/php/ext/google/protobuf/encode_decode.c +++ b/php/ext/google/protobuf/encode_decode.c @@ -999,6 +999,12 @@ static void* wrapper_submsg_handler(void* closure, const void* hd) { frame->submsg = submsg; frame->is_msg = true; } else { + if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) { + // Needs to initiate the wrapper message + const upb_msgdef* msgdef = subdesc->msgdef; + const upb_fielddef* f = upb_msgdef_itof(msgdef, 1); + native_slot_get_default(upb_fielddef_type(f), cached TSRMLS_CC); + } // In this case, wrapper message hasn't been created and value will be // stored in cache directly. frame->submsg = cached; @@ -1024,6 +1030,12 @@ static void* wrapper_oneofsubmsg_handler(void* closure, const void* hd) { if (oldcase != oneofdata->oneof_case_num) { oneof_cleanup(msg, oneofdata); + if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) { + // Needs to initiate the wrapper message + const upb_msgdef* msgdef = subdesc->msgdef; + const upb_fielddef* f = upb_msgdef_itof(msgdef, 1); + native_slot_get_default(upb_fielddef_type(f), cached TSRMLS_CC); + } frame->submsg = cached; frame->is_msg = false; } else if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_OBJECT) { diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php index 53cd526e4f..319e3321d2 100644 --- a/php/tests/encode_decode_test.php +++ b/php/tests/encode_decode_test.php @@ -1164,6 +1164,18 @@ class EncodeDecodeTest extends TestBase $m->serializeToJsonString()); } + public function testEncodeAnyWithDefaultWrapperMessagePacked() + { + $any = new Any(); + $any->pack(new TestInt32Value([ + 'field' => new Int32Value(['value' => 0]), + ])); + $this->assertSame( + "{\"@type\":\"type.googleapis.com/foo.TestInt32Value\"," . + "\"field\":0}", + $any->serializeToJsonString()); + } + public function testDecodeTopLevelFieldMask() { $m = new TestMessage();