Skip to content

Commit dcc8b6b

Browse files
SpencerMalonesmalone1
authored andcommitted
Add option for PHP to emit default values.
1 parent 6643af3 commit dcc8b6b

File tree

6 files changed

+295
-38
lines changed

6 files changed

+295
-38
lines changed

php/ext/google/protobuf/message.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,9 @@ PHP_METHOD(Message, serializeToJsonString) {
773773
if (Z_LVAL_P(flags) & PRESERVE_PROTO_FIELD_NAMES) {
774774
options |= upb_JsonEncode_UseProtoNames;
775775
}
776+
if (Z_LVAL_P(flags) & EMIT_DEFAULTS) {
777+
options |= upb_JsonEncode_EmitDefaults;
778+
}
776779
}
777780

778781
upb_Status_Clear(&status);

php/ext/google/protobuf/print_options.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,7 @@ void PrintOptions_ModuleInit() {
2424
zend_declare_class_constant_long(options_ce, "ALWAYS_PRINT_ENUMS_AS_INTS",
2525
sizeof("ALWAYS_PRINT_ENUMS_AS_INTS") - 1,
2626
ALWAYS_PRINT_ENUMS_AS_INTS);
27+
zend_declare_class_constant_long(options_ce, "EMIT_DEFAULTS",
28+
sizeof("EMIT_DEFAULTS") - 1,
29+
EMIT_DEFAULTS);
2730
}

php/ext/google/protobuf/print_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#define PRESERVE_PROTO_FIELD_NAMES (1 << 0)
1212
#define ALWAYS_PRINT_ENUMS_AS_INTS (1 << 1)
13+
#define EMIT_DEFAULTS (1 << 2)
1314

1415
// Registers the PHP PrintOptions class.
1516
void PrintOptions_ModuleInit();

php/src/Google/Protobuf/Internal/Message.php

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,7 @@ public function serializeToStream(&$output)
14691469
*/
14701470
public function serializeToJsonStream(&$output)
14711471
{
1472+
$options = $output->getOptions();
14721473
if (is_a($this, 'Google\Protobuf\Any')) {
14731474
$output->writeRaw("{", 1);
14741475
$type_field = $this->desc->getFieldByNumber(1);
@@ -1487,7 +1488,7 @@ public function serializeToJsonStream(&$output)
14871488
} else {
14881489
$value_fields = $value_msg->desc->getField();
14891490
foreach ($value_fields as $field) {
1490-
if ($value_msg->existField($field)) {
1491+
if ($value_msg->existField($field, $options)) {
14911492
$output->writeRaw(",", 1);
14921493
if (!$value_msg->serializeFieldToJsonStream($output, $field)) {
14931494
return false;
@@ -1513,7 +1514,7 @@ public function serializeToJsonStream(&$output)
15131514
$output->writeRaw($timestamp, strlen($timestamp));
15141515
} elseif (get_class($this) === 'Google\Protobuf\ListValue') {
15151516
$field = $this->desc->getField()[1];
1516-
if (!$this->existField($field)) {
1517+
if (!$this->existField($field, $options)) {
15171518
$output->writeRaw("[]", 2);
15181519
} else {
15191520
if (!$this->serializeFieldToJsonStream($output, $field)) {
@@ -1522,7 +1523,7 @@ public function serializeToJsonStream(&$output)
15221523
}
15231524
} elseif (get_class($this) === 'Google\Protobuf\Struct') {
15241525
$field = $this->desc->getField()[1];
1525-
if (!$this->existField($field)) {
1526+
if (!$this->existField($field, $options)) {
15261527
$output->writeRaw("{}", 2);
15271528
} else {
15281529
if (!$this->serializeFieldToJsonStream($output, $field)) {
@@ -1536,7 +1537,7 @@ public function serializeToJsonStream(&$output)
15361537
$fields = $this->desc->getField();
15371538
$first = true;
15381539
foreach ($fields as $field) {
1539-
if ($this->existField($field) ||
1540+
if ($this->existField($field, $options) ||
15401541
GPBUtil::hasJsonValue($this)) {
15411542
if ($first) {
15421543
$first = false;
@@ -1580,7 +1581,7 @@ public function serializeToJsonString($options = 0)
15801581
/**
15811582
* @ignore
15821583
*/
1583-
private function existField($field)
1584+
private function existField($field, $options = 0)
15841585
{
15851586
$getter = $field->getGetter();
15861587
$hazzer = "has" . substr($getter, 3);
@@ -1597,10 +1598,19 @@ private function existField($field)
15971598

15981599
$values = $this->$getter();
15991600
if ($field->isMap()) {
1601+
if (($options & \Google\Protobuf\PrintOptions::EMIT_DEFAULTS)) {
1602+
return true;
1603+
}
16001604
return count($values) !== 0;
16011605
} elseif ($field->isRepeated()) {
1606+
if (($options & \Google\Protobuf\PrintOptions::EMIT_DEFAULTS)) {
1607+
return true;
1608+
}
16021609
return count($values) !== 0;
16031610
} else {
1611+
if (($options & \Google\Protobuf\PrintOptions::EMIT_DEFAULTS)) {
1612+
return true;
1613+
}
16041614
return $values !== $this->defaultValue($field);
16051615
}
16061616
}
@@ -1863,7 +1873,7 @@ private function fieldJsonByteSize($field, $options = 0)
18631873
$getter = $field->getGetter();
18641874
$values = $this->$getter();
18651875
$count = count($values);
1866-
if ($count !== 0) {
1876+
if ($count !== 0 || ($options & \Google\Protobuf\PrintOptions::EMIT_DEFAULTS)) {
18671877
if (!GPBUtil::hasSpecialJsonMapping($this)) {
18681878
$size += 3; // size for "\"\":".
18691879
if ($options & PrintOptions::PRESERVE_PROTO_FIELD_NAMES) {
@@ -1873,37 +1883,39 @@ private function fieldJsonByteSize($field, $options = 0)
18731883
} // size for field name
18741884
}
18751885
$size += 2; // size for "{}".
1876-
$size += $count - 1; // size for commas
1877-
$getter = $field->getGetter();
1878-
$map_entry = $field->getMessageType();
1879-
$key_field = $map_entry->getFieldByNumber(1);
1880-
$value_field = $map_entry->getFieldByNumber(2);
1881-
switch ($key_field->getType()) {
1882-
case GPBType::STRING:
1883-
case GPBType::SFIXED64:
1884-
case GPBType::INT64:
1885-
case GPBType::SINT64:
1886-
case GPBType::FIXED64:
1887-
case GPBType::UINT64:
1888-
$additional_quote = false;
1889-
break;
1890-
default:
1891-
$additional_quote = true;
1892-
}
1893-
foreach ($values as $key => $value) {
1894-
if ($additional_quote) {
1895-
$size += 2; // size for ""
1886+
if ($count > 0) {
1887+
$size += $count - 1; // size for commas
1888+
$getter = $field->getGetter();
1889+
$map_entry = $field->getMessageType();
1890+
$key_field = $map_entry->getFieldByNumber(1);
1891+
$value_field = $map_entry->getFieldByNumber(2);
1892+
switch ($key_field->getType()) {
1893+
case GPBType::STRING:
1894+
case GPBType::SFIXED64:
1895+
case GPBType::INT64:
1896+
case GPBType::SINT64:
1897+
case GPBType::FIXED64:
1898+
case GPBType::UINT64:
1899+
$additional_quote = false;
1900+
break;
1901+
default:
1902+
$additional_quote = true;
1903+
}
1904+
foreach ($values as $key => $value) {
1905+
if ($additional_quote) {
1906+
$size += 2; // size for ""
1907+
}
1908+
$size += $this->fieldDataOnlyJsonByteSize($key_field, $key, $options);
1909+
$size += $this->fieldDataOnlyJsonByteSize($value_field, $value, $options);
1910+
$size += 1; // size for :
18961911
}
1897-
$size += $this->fieldDataOnlyJsonByteSize($key_field, $key, $options);
1898-
$size += $this->fieldDataOnlyJsonByteSize($value_field, $value, $options);
1899-
$size += 1; // size for :
19001912
}
19011913
}
19021914
} elseif ($field->isRepeated()) {
19031915
$getter = $field->getGetter();
19041916
$values = $this->$getter();
19051917
$count = count($values);
1906-
if ($count !== 0) {
1918+
if ($count !== 0 || ($options & \Google\Protobuf\PrintOptions::EMIT_DEFAULTS)) {
19071919
if (!GPBUtil::hasSpecialJsonMapping($this)) {
19081920
$size += 3; // size for "\"\":".
19091921
if ($options & PrintOptions::PRESERVE_PROTO_FIELD_NAMES) {
@@ -1913,13 +1925,15 @@ private function fieldJsonByteSize($field, $options = 0)
19131925
} // size for field name
19141926
}
19151927
$size += 2; // size for "[]".
1916-
$size += $count - 1; // size for commas
1917-
$getter = $field->getGetter();
1918-
foreach ($values as $value) {
1919-
$size += $this->fieldDataOnlyJsonByteSize($field, $value, $options);
1928+
if ($count > 0) {
1929+
$size += $count - 1; // size for commas
1930+
$getter = $field->getGetter();
1931+
foreach ($values as $value) {
1932+
$size += $this->fieldDataOnlyJsonByteSize($field, $value, $options);
1933+
}
19201934
}
19211935
}
1922-
} elseif ($this->existField($field) || GPBUtil::hasJsonValue($this)) {
1936+
} elseif ($this->existField($field, $options) || GPBUtil::hasJsonValue($this)) {
19231937
if (!GPBUtil::hasSpecialJsonMapping($this)) {
19241938
$size += 3; // size for "\"\":".
19251939
if ($options & PrintOptions::PRESERVE_PROTO_FIELD_NAMES) {
@@ -2017,7 +2031,7 @@ public function jsonByteSize($options = 0)
20172031
$size += strlen($timestamp);
20182032
} elseif (get_class($this) === 'Google\Protobuf\ListValue') {
20192033
$field = $this->desc->getField()[1];
2020-
if ($this->existField($field)) {
2034+
if ($this->existField($field, $options)) {
20212035
$field_size = $this->fieldJsonByteSize($field, $options);
20222036
$size += $field_size;
20232037
} else {
@@ -2026,7 +2040,7 @@ public function jsonByteSize($options = 0)
20262040
}
20272041
} elseif (get_class($this) === 'Google\Protobuf\Struct') {
20282042
$field = $this->desc->getField()[1];
2029-
if ($this->existField($field)) {
2043+
if ($this->existField($field, $options)) {
20302044
$field_size = $this->fieldJsonByteSize($field, $options);
20312045
$size += $field_size;
20322046
} else {

php/src/Google/Protobuf/PrintOptions.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ class PrintOptions
1313
{
1414
const PRESERVE_PROTO_FIELD_NAMES = 1 << 0;
1515
const ALWAYS_PRINT_ENUMS_AS_INTS = 1 << 1;
16-
}
16+
const EMIT_DEFAULTS = 1 << 2;
17+
}

0 commit comments

Comments
 (0)