Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions php/ext/google/protobuf/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,9 @@ PHP_METHOD(Message, serializeToJsonString) {
if (Z_LVAL_P(flags) & PRESERVE_PROTO_FIELD_NAMES) {
options |= upb_JsonEncode_UseProtoNames;
}
if (Z_LVAL_P(flags) & EMIT_DEFAULTS) {
options |= upb_JsonEncode_EmitDefaults;
}
}

upb_Status_Clear(&status);
Expand Down
3 changes: 3 additions & 0 deletions php/ext/google/protobuf/print_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ void PrintOptions_ModuleInit() {
zend_declare_class_constant_long(options_ce, "ALWAYS_PRINT_ENUMS_AS_INTS",
sizeof("ALWAYS_PRINT_ENUMS_AS_INTS") - 1,
ALWAYS_PRINT_ENUMS_AS_INTS);
zend_declare_class_constant_long(options_ce, "EMIT_DEFAULTS",
sizeof("EMIT_DEFAULTS") - 1,
EMIT_DEFAULTS);
}
1 change: 1 addition & 0 deletions php/ext/google/protobuf/print_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#define PRESERVE_PROTO_FIELD_NAMES (1 << 0)
#define ALWAYS_PRINT_ENUMS_AS_INTS (1 << 1)
#define EMIT_DEFAULTS (1 << 2)

// Registers the PHP PrintOptions class.
void PrintOptions_ModuleInit();
Expand Down
96 changes: 59 additions & 37 deletions php/src/Google/Protobuf/Internal/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,14 @@ protected function whichOneof($oneof_name)
return $field->getName();
}

/**
* @ignore
*/
private function shouldEmitDefaults($options): bool
{
return ($options & \Google\Protobuf\PrintOptions::EMIT_DEFAULTS) !== 0;
}

/**
* @ignore
*/
Expand Down Expand Up @@ -1469,6 +1477,7 @@ public function serializeToStream(&$output)
*/
public function serializeToJsonStream(&$output)
{
$options = $output->getOptions();
if (is_a($this, 'Google\Protobuf\Any')) {
$output->writeRaw("{", 1);
$type_field = $this->desc->getFieldByNumber(1);
Expand All @@ -1487,7 +1496,7 @@ public function serializeToJsonStream(&$output)
} else {
$value_fields = $value_msg->desc->getField();
foreach ($value_fields as $field) {
if ($value_msg->existField($field)) {
if ($value_msg->existField($field, $options)) {
$output->writeRaw(",", 1);
if (!$value_msg->serializeFieldToJsonStream($output, $field)) {
return false;
Expand All @@ -1513,7 +1522,7 @@ public function serializeToJsonStream(&$output)
$output->writeRaw($timestamp, strlen($timestamp));
} elseif (get_class($this) === 'Google\Protobuf\ListValue') {
$field = $this->desc->getField()[1];
if (!$this->existField($field)) {
if (!$this->existField($field, $options)) {
$output->writeRaw("[]", 2);
} else {
if (!$this->serializeFieldToJsonStream($output, $field)) {
Expand All @@ -1522,7 +1531,7 @@ public function serializeToJsonStream(&$output)
}
} elseif (get_class($this) === 'Google\Protobuf\Struct') {
$field = $this->desc->getField()[1];
if (!$this->existField($field)) {
if (!$this->existField($field, $options)) {
$output->writeRaw("{}", 2);
} else {
if (!$this->serializeFieldToJsonStream($output, $field)) {
Expand All @@ -1536,7 +1545,7 @@ public function serializeToJsonStream(&$output)
$fields = $this->desc->getField();
$first = true;
foreach ($fields as $field) {
if ($this->existField($field) ||
if ($this->existField($field, $options) ||
GPBUtil::hasJsonValue($this)) {
if ($first) {
$first = false;
Expand Down Expand Up @@ -1580,7 +1589,7 @@ public function serializeToJsonString($options = 0)
/**
* @ignore
*/
private function existField($field)
private function existField($field, $options = 0)
{
$getter = $field->getGetter();
$hazzer = "has" . substr($getter, 3);
Expand All @@ -1597,10 +1606,19 @@ private function existField($field)

$values = $this->$getter();
if ($field->isMap()) {
if ($this->shouldEmitDefaults($options)) {
return true;
}
return count($values) !== 0;
} elseif ($field->isRepeated()) {
if ($this->shouldEmitDefaults($options)) {
return true;
}
return count($values) !== 0;
} else {
if ($this->shouldEmitDefaults($options)) {
return true;
}
return $values !== $this->defaultValue($field);
}
}
Expand Down Expand Up @@ -1863,7 +1881,7 @@ private function fieldJsonByteSize($field, $options = 0)
$getter = $field->getGetter();
$values = $this->$getter();
$count = count($values);
if ($count !== 0) {
if ($count !== 0 || $this->shouldEmitDefaults($options)) {
if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += 3; // size for "\"\":".
if ($options & PrintOptions::PRESERVE_PROTO_FIELD_NAMES) {
Expand All @@ -1873,37 +1891,39 @@ private function fieldJsonByteSize($field, $options = 0)
} // size for field name
}
$size += 2; // size for "{}".
$size += $count - 1; // size for commas
$getter = $field->getGetter();
$map_entry = $field->getMessageType();
$key_field = $map_entry->getFieldByNumber(1);
$value_field = $map_entry->getFieldByNumber(2);
switch ($key_field->getType()) {
case GPBType::STRING:
case GPBType::SFIXED64:
case GPBType::INT64:
case GPBType::SINT64:
case GPBType::FIXED64:
case GPBType::UINT64:
$additional_quote = false;
break;
default:
$additional_quote = true;
}
foreach ($values as $key => $value) {
if ($additional_quote) {
$size += 2; // size for ""
if ($count > 0) {
$size += $count - 1; // size for commas
$getter = $field->getGetter();
$map_entry = $field->getMessageType();
$key_field = $map_entry->getFieldByNumber(1);
$value_field = $map_entry->getFieldByNumber(2);
switch ($key_field->getType()) {
case GPBType::STRING:
case GPBType::SFIXED64:
case GPBType::INT64:
case GPBType::SINT64:
case GPBType::FIXED64:
case GPBType::UINT64:
$additional_quote = false;
break;
default:
$additional_quote = true;
}
foreach ($values as $key => $value) {
if ($additional_quote) {
$size += 2; // size for ""
}
$size += $this->fieldDataOnlyJsonByteSize($key_field, $key, $options);
$size += $this->fieldDataOnlyJsonByteSize($value_field, $value, $options);
$size += 1; // size for :
}
$size += $this->fieldDataOnlyJsonByteSize($key_field, $key, $options);
$size += $this->fieldDataOnlyJsonByteSize($value_field, $value, $options);
$size += 1; // size for :
}
}
} elseif ($field->isRepeated()) {
$getter = $field->getGetter();
$values = $this->$getter();
$count = count($values);
if ($count !== 0) {
if ($count !== 0 || $this->shouldEmitDefaults($options)) {
if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += 3; // size for "\"\":".
if ($options & PrintOptions::PRESERVE_PROTO_FIELD_NAMES) {
Expand All @@ -1913,13 +1933,15 @@ private function fieldJsonByteSize($field, $options = 0)
} // size for field name
}
$size += 2; // size for "[]".
$size += $count - 1; // size for commas
$getter = $field->getGetter();
foreach ($values as $value) {
$size += $this->fieldDataOnlyJsonByteSize($field, $value, $options);
if ($count > 0) {
$size += $count - 1; // size for commas
$getter = $field->getGetter();
foreach ($values as $value) {
$size += $this->fieldDataOnlyJsonByteSize($field, $value, $options);
}
}
}
} elseif ($this->existField($field) || GPBUtil::hasJsonValue($this)) {
} elseif ($this->existField($field, $options) || GPBUtil::hasJsonValue($this)) {
if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += 3; // size for "\"\":".
if ($options & PrintOptions::PRESERVE_PROTO_FIELD_NAMES) {
Expand Down Expand Up @@ -2017,7 +2039,7 @@ public function jsonByteSize($options = 0)
$size += strlen($timestamp);
} elseif (get_class($this) === 'Google\Protobuf\ListValue') {
$field = $this->desc->getField()[1];
if ($this->existField($field)) {
if ($this->existField($field, $options)) {
$field_size = $this->fieldJsonByteSize($field, $options);
$size += $field_size;
} else {
Expand All @@ -2026,7 +2048,7 @@ public function jsonByteSize($options = 0)
}
} elseif (get_class($this) === 'Google\Protobuf\Struct') {
$field = $this->desc->getField()[1];
if ($this->existField($field)) {
if ($this->existField($field, $options)) {
$field_size = $this->fieldJsonByteSize($field, $options);
$size += $field_size;
} else {
Expand Down
3 changes: 2 additions & 1 deletion php/src/Google/Protobuf/PrintOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ class PrintOptions
{
const PRESERVE_PROTO_FIELD_NAMES = 1 << 0;
const ALWAYS_PRINT_ENUMS_AS_INTS = 1 << 1;
}
const EMIT_DEFAULTS = 1 << 2;
}
Loading
Loading