Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to keep default values in serialized JSON #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
# protobuf-php
This repository contains only PHP files to support Composer installation. This repository is a mirror of [protobuf](https://github.com/protocolbuffers/protobuf). Any support requests, bug reports, or development contributions should be directed to that project. To install protobuf for PHP, please see https://github.com/protocolbuffers/protobuf/tree/master/php

Features:
* Keep default values in generated JSON.
By default protobuf compiler strips all default values. In some cases it can be needed to keep them. It can be triggered by code below:
````
GPBWire::setKeepDefaultValues(true);
````
10 changes: 10 additions & 0 deletions src/Google/Protobuf/Internal/GPBWire.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ class GPBWire
const NORMAL_FORMAT = 1;
const PACKED_FORMAT = 2;

private static $keepDefaultValues = false;

public static function setKeepDefaultValues($keepDefaultValues) {
self::$keepDefaultValues = (bool) $keepDefaultValues;
}

public static function getKeepDefaultValues() {
return self::$keepDefaultValues;
}

public static function getTagFieldNumber($tag)
{
return ($tag >> self::TAG_TYPE_BITS) &
Expand Down
116 changes: 79 additions & 37 deletions src/Google/Protobuf/Internal/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ private function initWithGeneratedPool()
$oneof_name = $oneof->getName();
$this->$oneof_name = new OneofField($oneof);
} else if ($field->getLabel() === GPBLabel::OPTIONAL &&
PHP_INT_SIZE == 4) {
PHP_INT_SIZE == 4) {
switch ($field->getType()) {
case GPBType::INT64:
case GPBType::UINT64:
Expand All @@ -175,6 +175,42 @@ private function initWithDescriptor(Descriptor $desc)
}
}

protected function readWrapperValue($member)
{
$field = $this->desc->getFieldByName($member);
$oneof_index = $field->getOneofIndex();
if ($oneof_index === -1) {
$wrapper = $this->$member;
} else {
$wrapper = $this->readOneof($field->getNumber());
}

if (is_null($wrapper)) {
return NULL;
} else {
return $wrapper->getValue();
}
}

protected function writeWrapperValue($member, $value)
{
$field = $this->desc->getFieldByName($member);
$wrapped_value = $value;
if (!is_null($value)) {
$desc = $field->getMessageType();
$klass = $desc->getClass();
$wrapped_value = new $klass;
$wrapped_value->setValue($value);
}

$oneof_index = $field->getOneofIndex();
if ($oneof_index === -1) {
$this->$member = $wrapped_value;
} else {
$this->writeOneof($field->getNumber(), $wrapped_value);
}
}

protected function readOneof($number)
{
$field = $this->desc->getFieldByNumber($number);
Expand Down Expand Up @@ -204,7 +240,7 @@ protected function whichOneof($oneof_name)
$oneof_field = $this->$oneof_name;
$number = $oneof_field->getNumber();
if ($number == 0) {
return "";
return "";
}
$field = $this->desc->getFieldByNumber($number);
return $field->getName();
Expand Down Expand Up @@ -827,7 +863,7 @@ private function convertJsonValueToProtoValue(
return $enum_value->getNumber();
}
throw new GPBDecodeException(
"Enum field only accepts integer or enum value name");
"Enum field only accepts integer or enum value name");
case GPBType::STRING:
if (is_null($value)) {
return $this->defaultValue($field);
Expand Down Expand Up @@ -894,16 +930,16 @@ private function convertJsonValueToProtoValue(
return $this->defaultValue($field);
}
if (!is_numeric($value)) {
throw new GPBDecodeException(
"Invalid data type for int32 field");
throw new GPBDecodeException(
"Invalid data type for int32 field");
}
if (bccomp($value, "2147483647") > 0) {
throw new GPBDecodeException(
"Int32 too large");
throw new GPBDecodeException(
"Int32 too large");
}
if (bccomp($value, "-2147483648") < 0) {
throw new GPBDecodeException(
"Int32 too small");
throw new GPBDecodeException(
"Int32 too small");
}
return $value;
case GPBType::UINT32:
Expand All @@ -912,8 +948,8 @@ private function convertJsonValueToProtoValue(
return $this->defaultValue($field);
}
if (!is_numeric($value)) {
throw new GPBDecodeException(
"Invalid data type for uint32 field");
throw new GPBDecodeException(
"Invalid data type for uint32 field");
}
if (bccomp($value, 4294967295) > 0) {
throw new GPBDecodeException(
Expand All @@ -927,8 +963,8 @@ private function convertJsonValueToProtoValue(
return $this->defaultValue($field);
}
if (!is_numeric($value)) {
throw new GPBDecodeException(
"Invalid data type for int64 field");
throw new GPBDecodeException(
"Invalid data type for int64 field");
}
if (bccomp($value, "9223372036854775807") > 0) {
throw new GPBDecodeException(
Expand All @@ -945,8 +981,8 @@ private function convertJsonValueToProtoValue(
return $this->defaultValue($field);
}
if (!is_numeric($value)) {
throw new GPBDecodeException(
"Invalid data type for int64 field");
throw new GPBDecodeException(
"Invalid data type for int64 field");
}
if (bccomp($value, "18446744073709551615") > 0) {
throw new GPBDecodeException(
Expand Down Expand Up @@ -1032,7 +1068,7 @@ private static function normalizeArrayElementsToMessageType(&$value, $class)
} else {
// Normalize each element in the array.
foreach ($value as $key => &$elementValue) {
self::normalizeToMessageType($elementValue, $class);
self::normalizeToMessageType($elementValue, $class);
}
}
}
Expand Down Expand Up @@ -1243,11 +1279,11 @@ public function parseFromJsonStream($input)
}
if (is_null($array)) {
if ($this instanceof \Google\Protobuf\Value) {
$this->setNullValue(\Google\Protobuf\NullValue::NULL_VALUE);
return;
$this->setNullValue(\Google\Protobuf\NullValue::NULL_VALUE);
return;
} else {
throw new GPBDecodeException(
"Cannot decode json string: " . $input->getData());
throw new GPBDecodeException(
"Cannot decode json string: " . $input->getData());
}
}
try {
Expand Down Expand Up @@ -1504,9 +1540,14 @@ private function existField($field)
$oneof_name = $oneof->getName();
return $this->$oneof_name->getNumber() === $field->getNumber();
}

$getter = $field->getGetter();
$values = $this->$getter();

if (GPBWire::getKeepDefaultValues() && $values !== null) {
return true;
}

if ($field->isMap()) {
return count($values) !== 0;
} elseif ($field->isRepeated()) {
Expand Down Expand Up @@ -1618,7 +1659,7 @@ private function fieldDataOnlyJsonByteSize($field, $value)
if ($value < 0) {
$value = bcadd($value, "18446744073709551616");
}
// Intentional fall through.
// Intentional fall through.
case GPBType::SFIXED64:
case GPBType::INT64:
case GPBType::SINT64:
Expand Down Expand Up @@ -1684,7 +1725,8 @@ private function fieldDataOnlyJsonByteSize($field, $value)
$size += 2; // size for \"\"
break;
case GPBType::MESSAGE:
$size += $value->jsonByteSize();
// 4 for null
$size += $value !== null ? $value->jsonByteSize() : 4;
break;
# case GPBType::GROUP:
# // TODO(teboring): Add support.
Expand Down Expand Up @@ -1770,7 +1812,7 @@ private function fieldJsonByteSize($field)
$getter = $field->getGetter();
$values = $this->$getter();
$count = count($values);
if ($count !== 0) {
if (GPBWire::getKeepDefaultValues() || $count !== 0) {
if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += 3; // size for "\"\":".
$size += strlen($field->getJsonName()); // size for field name
Expand All @@ -1782,16 +1824,16 @@ private function fieldJsonByteSize($field)
$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;
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) {
Expand All @@ -1806,13 +1848,13 @@ private function fieldJsonByteSize($field)
$getter = $field->getGetter();
$values = $this->$getter();
$count = count($values);
if ($count !== 0) {
if (GPBWire::getKeepDefaultValues() || $count !== 0) {
if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += 3; // size for "\"\":".
$size += strlen($field->getJsonName()); // size for field name
}
$size += 2; // size for "[]".
$size += $count - 1; // size for commas
$size += max($count - 1, 0); // size for commas
$getter = $field->getGetter();
foreach ($values as $value) {
$size += $this->fieldDataOnlyJsonByteSize($field, $value);
Expand Down Expand Up @@ -1936,7 +1978,7 @@ public function jsonByteSize()
$field_size = $this->fieldJsonByteSize($field);
$size += $field_size;
if ($field_size != 0) {
$count++;
$count++;
}
}
// size for comma
Expand Down