Эх сурвалжийг харах

Merge pull request #4395 from stone4774/fixbug_enum2json2

Fix bug: whether always_print_enums_as_ints is true or false, it alwa…
Feng Xiao 7 жил өмнө
parent
commit
ac673763f7

+ 17 - 14
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 {

+ 17 - 3
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_;

+ 6 - 0
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;
+}

+ 2 - 0
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);

+ 24 - 0
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.