Merge pull request #2867 from mojoBrendan/master

Add preserve_proto_field_names option to JsonPrintOptions
pull/2887/head
Feng Xiao 8 years ago committed by GitHub
commit 15b60bccf8
  1. 22
      src/google/protobuf/util/internal/default_value_objectwriter.cc
  2. 11
      src/google/protobuf/util/internal/default_value_objectwriter.h
  3. 6
      src/google/protobuf/util/internal/protostream_objectsource.cc
  4. 8
      src/google/protobuf/util/internal/protostream_objectsource.h
  5. 4
      src/google/protobuf/util/json_util.cc
  6. 5
      src/google/protobuf/util/json_util.h
  7. 37
      src/google/protobuf/util/json_util_test.cc

@ -65,6 +65,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter(
current_(NULL), current_(NULL),
root_(NULL), root_(NULL),
suppress_empty_list_(false), suppress_empty_list_(false),
preserve_proto_field_names_(false),
field_scrub_callback_(NULL), field_scrub_callback_(NULL),
ow_(ow) {} ow_(ow) {}
@ -191,7 +192,8 @@ void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
DefaultValueObjectWriter::Node::Node( DefaultValueObjectWriter::Node::Node(
const string& name, const google::protobuf::Type* type, NodeKind kind, const string& name, const google::protobuf::Type* type, NodeKind kind,
const DataPiece& data, bool is_placeholder, const std::vector<string>& path, const DataPiece& data, bool is_placeholder, const std::vector<string>& path,
bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback) bool suppress_empty_list, bool preserve_proto_field_names,
FieldScrubCallBack* field_scrub_callback)
: name_(name), : name_(name),
type_(type), type_(type),
kind_(kind), kind_(kind),
@ -200,6 +202,7 @@ DefaultValueObjectWriter::Node::Node(
is_placeholder_(is_placeholder), is_placeholder_(is_placeholder),
path_(path), path_(path),
suppress_empty_list_(suppress_empty_list), suppress_empty_list_(suppress_empty_list),
preserve_proto_field_names_(preserve_proto_field_names),
field_scrub_callback_(field_scrub_callback) {} field_scrub_callback_(field_scrub_callback) {}
DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
@ -370,10 +373,12 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
// If the child field is of primitive type, sets its data to the default // If the child field is of primitive type, sets its data to the default
// value of its type. // value of its type.
google::protobuf::scoped_ptr<Node> child(new Node( google::protobuf::scoped_ptr<Node> child(new Node(
field.json_name(), field_type, kind, preserve_proto_field_names_ ? field.name() : field.json_name(),
field_type, kind,
kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo) kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo)
: DataPiece::NullData(), : DataPiece::NullData(),
true, path, suppress_empty_list_, field_scrub_callback_)); true, path, suppress_empty_list_, preserve_proto_field_names_,
field_scrub_callback_));
new_children.push_back(child.release()); new_children.push_back(child.release());
} }
// Adds all leftover nodes in children_ to the beginning of new_child. // Adds all leftover nodes in children_ to the beginning of new_child.
@ -470,6 +475,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
std::vector<string> path; std::vector<string> path;
root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(), root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
false, path, suppress_empty_list_, false, path, suppress_empty_list_,
preserve_proto_field_names_,
field_scrub_callback_.get())); field_scrub_callback_.get()));
root_->PopulateChildren(typeinfo_); root_->PopulateChildren(typeinfo_);
current_ = root_.get(); current_ = root_.get();
@ -486,7 +492,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
: NULL), : NULL),
OBJECT, DataPiece::NullData(), false, OBJECT, DataPiece::NullData(), false,
child == NULL ? current_->path() : child->path(), child == NULL ? current_->path() : child->path(),
suppress_empty_list_, field_scrub_callback_.get())); suppress_empty_list_, preserve_proto_field_names_,
field_scrub_callback_.get()));
child = node.get(); child = node.get();
current_->AddChild(node.release()); current_->AddChild(node.release());
} }
@ -518,6 +525,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
std::vector<string> path; std::vector<string> path;
root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(),
false, path, suppress_empty_list_, false, path, suppress_empty_list_,
preserve_proto_field_names_,
field_scrub_callback_.get())); field_scrub_callback_.get()));
current_ = root_.get(); current_ = root_.get();
return this; return this;
@ -528,7 +536,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
google::protobuf::scoped_ptr<Node> node( google::protobuf::scoped_ptr<Node> node(
new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false, new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false,
child == NULL ? current_->path() : child->path(), child == NULL ? current_->path() : child->path(),
suppress_empty_list_, field_scrub_callback_.get())); suppress_empty_list_, preserve_proto_field_names_,
field_scrub_callback_.get()));
child = node.get(); child = node.get();
current_->AddChild(node.release()); current_->AddChild(node.release());
} }
@ -589,7 +598,8 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
google::protobuf::scoped_ptr<Node> node( google::protobuf::scoped_ptr<Node> node(
new Node(name.ToString(), NULL, PRIMITIVE, data, false, new Node(name.ToString(), NULL, PRIMITIVE, data, false,
child == NULL ? current_->path() : child->path(), child == NULL ? current_->path() : child->path(),
suppress_empty_list_, field_scrub_callback_.get())); suppress_empty_list_, preserve_proto_field_names_,
field_scrub_callback_.get()));
current_->AddChild(node.release()); current_->AddChild(node.release());
} else { } else {
child->set_data(data); child->set_data(data);

@ -126,6 +126,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// are written. // are written.
void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; } void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; }
// If set to true, original proto field names are used
void set_preserve_proto_field_names(bool value) { preserve_proto_field_names_ = value; }
private: private:
enum NodeKind { enum NodeKind {
PRIMITIVE = 0, PRIMITIVE = 0,
@ -141,7 +144,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
Node(const string& name, const google::protobuf::Type* type, NodeKind kind, Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
const DataPiece& data, bool is_placeholder, const DataPiece& data, bool is_placeholder,
const std::vector<string>& path, bool suppress_empty_list, const std::vector<string>& path, bool suppress_empty_list,
FieldScrubCallBack* field_scrub_callback); bool preserve_proto_field_names, FieldScrubCallBack* field_scrub_callback);
virtual ~Node() { virtual ~Node() {
for (int i = 0; i < children_.size(); ++i) { for (int i = 0; i < children_.size(); ++i) {
delete children_[i]; delete children_[i];
@ -220,6 +223,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Whether to suppress empty list output. // Whether to suppress empty list output.
bool suppress_empty_list_; bool suppress_empty_list_;
// Whether to preserve original proto field names
bool preserve_proto_field_names_;
// Pointer to function for determining whether a field needs to be scrubbed // Pointer to function for determining whether a field needs to be scrubbed
// or not. This callback is owned by the creator of this node. // or not. This callback is owned by the creator of this node.
FieldScrubCallBack* field_scrub_callback_; FieldScrubCallBack* field_scrub_callback_;
@ -268,6 +274,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Whether to suppress output of empty lists. // Whether to suppress output of empty lists.
bool suppress_empty_list_; bool suppress_empty_list_;
// Whether to preserve original proto field names
bool preserve_proto_field_names_;
// Unique Pointer to function for determining whether a field needs to be // Unique Pointer to function for determining whether a field needs to be
// scrubbed or not. // scrubbed or not.
FieldScrubCallBackPtr field_scrub_callback_; FieldScrubCallBackPtr field_scrub_callback_;

@ -121,6 +121,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource(
type_(type), type_(type),
use_lower_camel_for_enums_(false), use_lower_camel_for_enums_(false),
use_ints_for_enums_(false), use_ints_for_enums_(false),
preserve_proto_field_names_(false),
recursion_depth_(0), recursion_depth_(0),
max_recursion_depth_(kDefaultMaxRecursionDepth), max_recursion_depth_(kDefaultMaxRecursionDepth),
render_unknown_fields_(false), render_unknown_fields_(false),
@ -137,6 +138,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource(
type_(type), type_(type),
use_lower_camel_for_enums_(false), use_lower_camel_for_enums_(false),
use_ints_for_enums_(false), use_ints_for_enums_(false),
preserve_proto_field_names_(false),
recursion_depth_(0), recursion_depth_(0),
max_recursion_depth_(kDefaultMaxRecursionDepth), max_recursion_depth_(kDefaultMaxRecursionDepth),
render_unknown_fields_(false), render_unknown_fields_(false),
@ -200,9 +202,13 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
last_tag = tag; last_tag = tag;
field = FindAndVerifyField(type, tag); field = FindAndVerifyField(type, tag);
if (field != NULL) { if (field != NULL) {
if (preserve_proto_field_names_) {
field_name = field->name();
} else {
field_name = field->json_name(); field_name = field->json_name();
} }
} }
}
if (field == NULL) { if (field == NULL) {
// If we didn't find a field, skip this unknown tag. // If we didn't find a field, skip this unknown tag.
// TODO(wpoon): Check return boolean value. // TODO(wpoon): Check return boolean value.

@ -116,6 +116,11 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
use_ints_for_enums_ = value; use_ints_for_enums_ = value;
} }
// Sets whether to use original proto field names
void set_preserve_proto_field_names(bool value) {
preserve_proto_field_names_ = value;
}
// Sets the max recursion depth of proto message to be deserialized. Proto // Sets the max recursion depth of proto message to be deserialized. Proto
// messages over this depth will fail to be deserialized. // messages over this depth will fail to be deserialized.
// Default value is 64. // Default value is 64.
@ -294,6 +299,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
// Whether to render enums as ints always. Defaults to false. // Whether to render enums as ints always. Defaults to false.
bool use_ints_for_enums_; bool use_ints_for_enums_;
// Whether to preserve proto field names
bool preserve_proto_field_names_;
// Tracks current recursion depth. // Tracks current recursion depth.
mutable int recursion_depth_; mutable int recursion_depth_;

@ -83,12 +83,16 @@ util::Status BinaryToJsonStream(TypeResolver* resolver,
RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type); converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type);
proto_source.set_use_ints_for_enums(options.always_print_enums_as_ints); proto_source.set_use_ints_for_enums(options.always_print_enums_as_ints);
proto_source.set_preserve_proto_field_names(
options.preserve_proto_field_names);
io::CodedOutputStream out_stream(json_output); io::CodedOutputStream out_stream(json_output);
converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "", converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "",
&out_stream); &out_stream);
if (options.always_print_primitive_fields) { if (options.always_print_primitive_fields) {
converter::DefaultValueObjectWriter default_value_writer( converter::DefaultValueObjectWriter default_value_writer(
resolver, type, &json_writer); resolver, type, &json_writer);
default_value_writer.set_preserve_proto_field_names(
options.preserve_proto_field_names);
return proto_source.WriteTo(&default_value_writer); return proto_source.WriteTo(&default_value_writer);
} else { } else {
return proto_source.WriteTo(&json_writer); return proto_source.WriteTo(&json_writer);

@ -64,10 +64,13 @@ struct JsonPrintOptions {
// Whether to always print enums as ints. By default they are rendered as // Whether to always print enums as ints. By default they are rendered as
// strings. // strings.
bool always_print_enums_as_ints; bool always_print_enums_as_ints;
// Whether to preserve proto field names
bool preserve_proto_field_names;
JsonPrintOptions() : add_whitespace(false), JsonPrintOptions() : add_whitespace(false),
always_print_primitive_fields(false), always_print_primitive_fields(false),
always_print_enums_as_ints(false) { always_print_enums_as_ints(false),
preserve_proto_field_names(false) {
} }
}; };

@ -159,6 +159,43 @@ TEST_F(JsonUtilTest, TestDefaultValues) {
"\"repeatedMessageValue\":[]" "\"repeatedMessageValue\":[]"
"}", "}",
ToJson(m, options)); ToJson(m, options));
options.preserve_proto_field_names = true;
m.set_string_value("i am a test string value");
m.set_bytes_value("i am a test bytes value");
EXPECT_EQ(
"{\"bool_value\":false,"
"\"int32_value\":0,"
"\"int64_value\":\"0\","
"\"uint32_value\":0,"
"\"uint64_value\":\"0\","
"\"float_value\":0,"
"\"double_value\":0,"
"\"string_value\":\"i am a test string value\","
"\"bytes_value\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
"\"enum_value\":\"FOO\","
"\"repeated_bool_value\":[],"
"\"repeated_int32_value\":[],"
"\"repeated_int64_value\":[],"
"\"repeated_uint32_value\":[],"
"\"repeated_uint64_value\":[],"
"\"repeated_float_value\":[],"
"\"repeated_double_value\":[],"
"\"repeated_string_value\":[],"
"\"repeated_bytes_value\":[],"
"\"repeated_enum_value\":[],"
"\"repeated_message_value\":[]"
"}",
ToJson(m, options));
}
TEST_F(JsonUtilTest, TestPreserveProtoFieldNames) {
TestMessage m;
m.mutable_message_value();
JsonPrintOptions options;
options.preserve_proto_field_names = true;
EXPECT_EQ("{\"message_value\":{}}", ToJson(m, options));
} }
TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) { TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {

Loading…
Cancel
Save