diff options
author | Feng Xiao <xfxyjwf@gmail.com> | 2018-03-26 13:35:44 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-26 13:35:44 -0700 |
commit | ac673763f7acb7db0608d8a792db102fe6c926c3 (patch) | |
tree | fbb75ba3b77968e87ae1fbfce56d54e92bdd005e | |
parent | 416d4180f0466f1582d4aeb58b40595d215922c6 (diff) | |
parent | c99f5278eb8dad6f42def88ce8b5a3453f6df4a8 (diff) | |
download | protobuf-ac673763f7acb7db0608d8a792db102fe6c926c3.tar.gz protobuf-ac673763f7acb7db0608d8a792db102fe6c926c3.tar.bz2 protobuf-ac673763f7acb7db0608d8a792db102fe6c926c3.zip |
Merge pull request #4395 from stone4774/fixbug_enum2json2
Fix bug: whether always_print_enums_as_ints is true or false, it alwa…
5 files changed, 66 insertions, 17 deletions
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 2826e90e..b41feb7a 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -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 { diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h index 02cf827a..6e71f9c8 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.h +++ b/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -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_; diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto index 8a0441c8..cbc3f81f 100644 --- a/src/google/protobuf/util/json_format_proto3.proto +++ b/src/google/protobuf/util/json_format_proto3.proto @@ -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; +}
\ No newline at end of file diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc index ea0cc2e4..f81a7a30 100644 --- a/src/google/protobuf/util/json_util.cc +++ b/src/google/protobuf/util/json_util.cc @@ -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); diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index dbd262f6..ed9092df 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -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. |