From 343f7785728a9e4776fe06ab8048a53c79f11f7d Mon Sep 17 00:00:00 2001 From: SpringHack Date: Wed, 4 Aug 2021 00:53:23 +0800 Subject: [PATCH] Fix default value of enum(int) in json_util with proto2 (#8835) --- .../internal/default_value_objectwriter.cc | 23 ++++++++++++++++--- src/google/protobuf/util/json_format.proto | 10 ++++++++ src/google/protobuf/util/json_util_test.cc | 19 +++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 74fd53f1d011..c9c691a97085 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -411,9 +411,6 @@ void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) { DataPiece DefaultValueObjectWriter::FindEnumDefault( const google::protobuf::Field& field, const TypeInfo* typeinfo, bool use_ints_for_enums) { - if (!field.default_value().empty()) - return DataPiece(field.default_value(), true); - const google::protobuf::Enum* enum_type = typeinfo->GetEnumByTypeUrl(field.type_url()); if (!enum_type) { @@ -421,6 +418,26 @@ DataPiece DefaultValueObjectWriter::FindEnumDefault( << "'"; return DataPiece::NullData(); } + if (!field.default_value().empty()) { + if (!use_ints_for_enums) { + return DataPiece(field.default_value(), true); + } else { + const std::string& enum_default_value_name = field.default_value(); + for (int enum_index = 0; + enum_index < enum_type->enumvalue_size(); + ++enum_index) { + auto& enum_value = enum_type->enumvalue(enum_index); + if (enum_value.name() == enum_default_value_name) + return DataPiece(enum_value.number()); + } + GOOGLE_LOG(WARNING) << "Could not find enum value '" + << enum_default_value_name + << "' with type '" + << field.type_url() + << "'"; + return DataPiece::NullData(); + } + } // We treat the first value as the default if none is specified. return enum_type->enumvalue_size() > 0 ? (use_ints_for_enums diff --git a/src/google/protobuf/util/json_format.proto b/src/google/protobuf/util/json_format.proto index 7434fc3e8182..7b7100d78841 100644 --- a/src/google/protobuf/util/json_format.proto +++ b/src/google/protobuf/util/json_format.proto @@ -128,3 +128,13 @@ message TestExtension { } optional string value = 1; } + +enum EnumValue { + PROTOCOL = 0; + BUFFER = 1; + DEFAULT = 2; +} + +message TestDefaultEnumValue { + optional EnumValue enum_value = 1 [default = DEFAULT]; +} diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index c5d831500895..76d3a709224a 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -241,6 +241,25 @@ TEST_F(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) { EXPECT_EQ(proto3::BAR, parsed.enum_value3()); } +TEST_F(JsonUtilTest, TestPrintProto2EnumAsIntWithDefaultValue) { + protobuf_unittest::TestDefaultEnumValue orig; + + JsonPrintOptions print_options; + // use enum as int + print_options.always_print_enums_as_ints = true; + print_options.always_print_primitive_fields = true; + + // result should be int rather than string + std::string expected_json = "{\"enumValue\":2}"; + EXPECT_EQ(expected_json, ToJson(orig, print_options)); + + protobuf_unittest::TestDefaultEnumValue parsed; + JsonParseOptions parse_options; + ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options)); + + EXPECT_EQ(protobuf_unittest::DEFAULT, parsed.enum_value()); +} + TEST_F(JsonUtilTest, ParseMessage) { // Some random message but good enough to verify that the parsing wrapper // functions are working properly.