Merge pull request #4395 from stone4774/fixbug_enum2json2
Fix bug: whether always_print_enums_as_ints is true or false, it alwa…
This commit is contained in:
commit
ac673763f7
@ -66,6 +66,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter(
|
||||
root_(nullptr),
|
||||
suppress_empty_list_(false),
|
||||
preserve_proto_field_names_(false),
|
||||
use_ints_for_enums_(false),
|
||||
field_scrub_callback_(nullptr),
|
||||
ow_(ow) {}
|
||||
|
||||
@ -200,10 +201,10 @@ DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode(
|
||||
DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode(
|
||||
const string& name, const google::protobuf::Type* type, NodeKind kind,
|
||||
const DataPiece& data, bool is_placeholder, const std::vector<string>& path,
|
||||
bool suppress_empty_list, bool preserve_proto_field_names,
|
||||
bool suppress_empty_list, bool preserve_proto_field_names, bool use_ints_for_enums,
|
||||
FieldScrubCallBack* field_scrub_callback) {
|
||||
return new Node(name, type, kind, data, is_placeholder, path,
|
||||
suppress_empty_list, preserve_proto_field_names,
|
||||
suppress_empty_list, preserve_proto_field_names, use_ints_for_enums,
|
||||
field_scrub_callback);
|
||||
}
|
||||
|
||||
@ -220,12 +221,13 @@ DefaultValueObjectWriter::Node::Node(
|
||||
path_(path),
|
||||
suppress_empty_list_(suppress_empty_list),
|
||||
preserve_proto_field_names_(false),
|
||||
use_ints_for_enums_(false),
|
||||
field_scrub_callback_(field_scrub_callback) {}
|
||||
|
||||
DefaultValueObjectWriter::Node::Node(
|
||||
const string& name, const google::protobuf::Type* type, NodeKind kind,
|
||||
const DataPiece& data, bool is_placeholder, const std::vector<string>& path,
|
||||
bool suppress_empty_list, bool preserve_proto_field_names,
|
||||
bool suppress_empty_list, bool preserve_proto_field_names, bool use_ints_for_enums,
|
||||
FieldScrubCallBack* field_scrub_callback)
|
||||
: name_(name),
|
||||
type_(type),
|
||||
@ -236,6 +238,7 @@ DefaultValueObjectWriter::Node::Node(
|
||||
path_(path),
|
||||
suppress_empty_list_(suppress_empty_list),
|
||||
preserve_proto_field_names_(preserve_proto_field_names),
|
||||
use_ints_for_enums_(use_ints_for_enums),
|
||||
field_scrub_callback_(field_scrub_callback) {}
|
||||
|
||||
DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
|
||||
@ -408,9 +411,9 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
|
||||
std::unique_ptr<Node> child(new Node(
|
||||
preserve_proto_field_names_ ? field.name() : field.json_name(),
|
||||
field_type, kind,
|
||||
kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo)
|
||||
kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo, use_ints_for_enums_)
|
||||
: DataPiece::NullData(),
|
||||
true, path, suppress_empty_list_, preserve_proto_field_names_,
|
||||
true, path, suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_,
|
||||
field_scrub_callback_));
|
||||
new_children.push_back(child.release());
|
||||
}
|
||||
@ -435,7 +438,7 @@ void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
|
||||
}
|
||||
|
||||
DataPiece DefaultValueObjectWriter::FindEnumDefault(
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo) {
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo, bool use_ints_for_enums) {
|
||||
if (!field.default_value().empty())
|
||||
return DataPiece(field.default_value(), true);
|
||||
|
||||
@ -448,12 +451,12 @@ DataPiece DefaultValueObjectWriter::FindEnumDefault(
|
||||
}
|
||||
// We treat the first value as the default if none is specified.
|
||||
return enum_type->enumvalue_size() > 0
|
||||
? DataPiece(enum_type->enumvalue(0).name(), true)
|
||||
? (use_ints_for_enums ? DataPiece(enum_type->enumvalue(0).number()) : DataPiece(enum_type->enumvalue(0).name(), true))
|
||||
: DataPiece::NullData();
|
||||
}
|
||||
|
||||
DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo) {
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo, bool use_ints_for_enums) {
|
||||
switch (field.kind()) {
|
||||
case google::protobuf::Field_Kind_TYPE_DOUBLE: {
|
||||
return DataPiece(ConvertTo<double>(
|
||||
@ -496,7 +499,7 @@ DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
|
||||
field.default_value(), &DataPiece::ToUint32, static_cast<uint32>(0)));
|
||||
}
|
||||
case google::protobuf::Field_Kind_TYPE_ENUM: {
|
||||
return FindEnumDefault(field, typeinfo);
|
||||
return FindEnumDefault(field, typeinfo, use_ints_for_enums);
|
||||
}
|
||||
default: { return DataPiece::NullData(); }
|
||||
}
|
||||
@ -508,7 +511,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
|
||||
std::vector<string> path;
|
||||
root_.reset(CreateNewNode(string(name), &type_, OBJECT,
|
||||
DataPiece::NullData(), false, path,
|
||||
suppress_empty_list_, preserve_proto_field_names_,
|
||||
suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_,
|
||||
field_scrub_callback_.get()));
|
||||
root_->PopulateChildren(typeinfo_);
|
||||
current_ = root_.get();
|
||||
@ -526,7 +529,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
|
||||
: nullptr),
|
||||
OBJECT, DataPiece::NullData(), false,
|
||||
child == nullptr ? current_->path() : child->path(),
|
||||
suppress_empty_list_, preserve_proto_field_names_,
|
||||
suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_,
|
||||
field_scrub_callback_.get()));
|
||||
child = node.get();
|
||||
current_->AddChild(node.release());
|
||||
@ -559,7 +562,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
|
||||
std::vector<string> path;
|
||||
root_.reset(CreateNewNode(string(name), &type_, LIST, DataPiece::NullData(),
|
||||
false, path, suppress_empty_list_,
|
||||
preserve_proto_field_names_,
|
||||
preserve_proto_field_names_, use_ints_for_enums_,
|
||||
field_scrub_callback_.get()));
|
||||
current_ = root_.get();
|
||||
return this;
|
||||
@ -570,7 +573,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
|
||||
std::unique_ptr<Node> node(
|
||||
CreateNewNode(string(name), nullptr, LIST, DataPiece::NullData(), false,
|
||||
child == nullptr ? current_->path() : child->path(),
|
||||
suppress_empty_list_, preserve_proto_field_names_,
|
||||
suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_,
|
||||
field_scrub_callback_.get()));
|
||||
child = node.get();
|
||||
current_->AddChild(node.release());
|
||||
@ -632,7 +635,7 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
|
||||
std::unique_ptr<Node> node(
|
||||
CreateNewNode(string(name), nullptr, PRIMITIVE, data, false,
|
||||
child == nullptr ? current_->path() : child->path(),
|
||||
suppress_empty_list_, preserve_proto_field_names_,
|
||||
suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_,
|
||||
field_scrub_callback_.get()));
|
||||
current_->AddChild(node.release());
|
||||
} else {
|
||||
|
@ -128,6 +128,12 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
preserve_proto_field_names_ = value;
|
||||
}
|
||||
|
||||
// If set to true, enums are rendered as ints from output when default values
|
||||
// are written.
|
||||
void set_print_enums_as_ints(bool value) {
|
||||
use_ints_for_enums_ = value;
|
||||
}
|
||||
|
||||
protected:
|
||||
enum NodeKind {
|
||||
PRIMITIVE = 0,
|
||||
@ -147,7 +153,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
|
||||
const DataPiece& data, bool is_placeholder,
|
||||
const std::vector<string>& path, bool suppress_empty_list,
|
||||
bool preserve_proto_field_names,
|
||||
bool preserve_proto_field_names, bool use_ints_for_enums,
|
||||
FieldScrubCallBack* field_scrub_callback);
|
||||
virtual ~Node() {
|
||||
for (int i = 0; i < children_.size(); ++i) {
|
||||
@ -230,6 +236,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
// Whether to preserve original proto field names
|
||||
bool preserve_proto_field_names_;
|
||||
|
||||
// Whether to always print enums as ints
|
||||
bool use_ints_for_enums_;
|
||||
|
||||
// Pointer to function for determining whether a field needs to be scrubbed
|
||||
// or not. This callback is owned by the creator of this node.
|
||||
FieldScrubCallBack* field_scrub_callback_;
|
||||
@ -253,11 +262,12 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
const std::vector<string>& path,
|
||||
bool suppress_empty_list,
|
||||
bool preserve_proto_field_names,
|
||||
bool use_ints_for_enums,
|
||||
FieldScrubCallBack* field_scrub_callback);
|
||||
|
||||
// Creates a DataPiece containing the default value of the type of the field.
|
||||
static DataPiece CreateDefaultDataPieceForField(
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo);
|
||||
const google::protobuf::Field& field, const TypeInfo* typeinfo, bool use_ints_for_enums);
|
||||
|
||||
protected:
|
||||
// Returns a pointer to current Node in tree.
|
||||
@ -279,7 +289,8 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
// there is no default. For proto3, where we cannot specify an explicit
|
||||
// default, a zero value will always be returned.
|
||||
static DataPiece FindEnumDefault(const google::protobuf::Field& field,
|
||||
const TypeInfo* typeinfo);
|
||||
const TypeInfo* typeinfo,
|
||||
bool use_ints_for_enums);
|
||||
|
||||
// Type information for all the types used in the descriptor. Used to find
|
||||
// google::protobuf::Type of nested messages/enums.
|
||||
@ -304,6 +315,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
|
||||
// Whether to preserve original proto field names
|
||||
bool preserve_proto_field_names_;
|
||||
|
||||
// Whether to always print enums as ints
|
||||
bool use_ints_for_enums_;
|
||||
|
||||
// Unique Pointer to function for determining whether a field needs to be
|
||||
// scrubbed or not.
|
||||
FieldScrubCallBackPtr field_scrub_callback_;
|
||||
|
@ -181,3 +181,9 @@ message TestCustomJsonName {
|
||||
message TestExtensions {
|
||||
.protobuf_unittest.TestAllExtensions extensions = 1;
|
||||
}
|
||||
|
||||
message TestEnumValue{
|
||||
EnumType enum_value1 = 1;
|
||||
EnumType enum_value2 = 2;
|
||||
EnumType enum_value3 = 3;
|
||||
}
|
@ -97,6 +97,8 @@ util::Status BinaryToJsonStream(TypeResolver* resolver,
|
||||
resolver, type, &json_writer);
|
||||
default_value_writer.set_preserve_proto_field_names(
|
||||
options.preserve_proto_field_names);
|
||||
default_value_writer.set_print_enums_as_ints(
|
||||
options.always_print_enums_as_ints);
|
||||
return proto_source.WriteTo(&default_value_writer);
|
||||
} else {
|
||||
return proto_source.WriteTo(&json_writer);
|
||||
|
@ -54,6 +54,7 @@ using proto3::BAR;
|
||||
using proto3::TestMessage;
|
||||
using proto3::TestMap;
|
||||
using proto3::TestOneof;
|
||||
using proto3::TestEnumValue;
|
||||
|
||||
static const char kTypeUrlPrefix[] = "type.googleapis.com";
|
||||
|
||||
@ -217,6 +218,29 @@ TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
|
||||
EXPECT_EQ(proto3::BAR, parsed.repeated_enum_value(1));
|
||||
}
|
||||
|
||||
TEST_F(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) {
|
||||
TestEnumValue orig;
|
||||
//orig.set_enum_value1(proto3::FOO)
|
||||
orig.set_enum_value2(proto3::FOO);
|
||||
orig.set_enum_value3(proto3::BAR);
|
||||
|
||||
JsonPrintOptions print_options;
|
||||
print_options.always_print_enums_as_ints = true;
|
||||
print_options.always_print_primitive_fields = true;
|
||||
|
||||
string expected_json = "{\"enumValue1\":0,\"enumValue2\":0,\"enumValue3\":1}";
|
||||
EXPECT_EQ(expected_json, ToJson(orig, print_options));
|
||||
|
||||
TestEnumValue parsed;
|
||||
JsonParseOptions parse_options;
|
||||
ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
|
||||
|
||||
EXPECT_EQ(proto3::FOO, parsed.enum_value1());
|
||||
EXPECT_EQ(proto3::FOO, parsed.enum_value2());
|
||||
EXPECT_EQ(proto3::BAR, parsed.enum_value3());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(JsonUtilTest, ParseMessage) {
|
||||
// Some random message but good enough to verify that the parsing warpper
|
||||
// functions are working properly.
|
||||
|
Loading…
Reference in New Issue
Block a user