Commit 1a8cbfd3 authored by Feng Xiao's avatar Feng Xiao Committed by GitHub

Merge pull request #2736 from na-ka-na/master3

Add an option to always print enums as ints in Json API
parents a9ab38c1 172e0a64
...@@ -120,6 +120,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( ...@@ -120,6 +120,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource(
own_typeinfo_(true), own_typeinfo_(true),
type_(type), type_(type),
use_lower_camel_for_enums_(false), use_lower_camel_for_enums_(false),
use_ints_for_enums_(false),
recursion_depth_(0), recursion_depth_(0),
max_recursion_depth_(kDefaultMaxRecursionDepth), max_recursion_depth_(kDefaultMaxRecursionDepth),
render_unknown_fields_(false), render_unknown_fields_(false),
...@@ -135,6 +136,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( ...@@ -135,6 +136,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource(
own_typeinfo_(false), own_typeinfo_(false),
type_(type), type_(type),
use_lower_camel_for_enums_(false), use_lower_camel_for_enums_(false),
use_ints_for_enums_(false),
recursion_depth_(0), recursion_depth_(0),
max_recursion_depth_(kDefaultMaxRecursionDepth), max_recursion_depth_(kDefaultMaxRecursionDepth),
render_unknown_fields_(false), render_unknown_fields_(false),
...@@ -858,6 +860,12 @@ Status ProtoStreamObjectSource::RenderNonMessageField( ...@@ -858,6 +860,12 @@ Status ProtoStreamObjectSource::RenderNonMessageField(
break; break;
} }
// No need to lookup enum type if we need to render int.
if (use_ints_for_enums_) {
ow->RenderInt32(field_name, buffer32);
break;
}
// Get the nested enum type for this field. // Get the nested enum type for this field.
// TODO(skarvaje): Avoid string manipulation. Find ways to speed this // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
// up. // up.
......
...@@ -110,6 +110,12 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { ...@@ -110,6 +110,12 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
use_lower_camel_for_enums_ = value; use_lower_camel_for_enums_ = value;
} }
// Sets whether to always output enums as ints, by default this is off, and
// enums are rendered as strings.
void set_use_ints_for_enums(bool value) {
use_ints_for_enums_ = 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.
...@@ -285,6 +291,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { ...@@ -285,6 +291,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
// Whether to render enums using lowerCamelCase. Defaults to false. // Whether to render enums using lowerCamelCase. Defaults to false.
bool use_lower_camel_for_enums_; bool use_lower_camel_for_enums_;
// Whether to render enums as ints always. Defaults to false.
bool use_ints_for_enums_;
// Tracks current recursion depth. // Tracks current recursion depth.
mutable int recursion_depth_; mutable int recursion_depth_;
......
...@@ -102,6 +102,7 @@ class ProtostreamObjectSourceTest ...@@ -102,6 +102,7 @@ class ProtostreamObjectSourceTest
mock_(), mock_(),
ow_(&mock_), ow_(&mock_),
use_lower_camel_for_enums_(false), use_lower_camel_for_enums_(false),
use_ints_for_enums_(false),
add_trailing_zeros_(false) { add_trailing_zeros_(false) {
helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor()); helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor());
} }
...@@ -123,6 +124,7 @@ class ProtostreamObjectSourceTest ...@@ -123,6 +124,7 @@ class ProtostreamObjectSourceTest
google::protobuf::scoped_ptr<ProtoStreamObjectSource> os( google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true); if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
if (use_ints_for_enums_) os->set_use_ints_for_enums(true);
os->set_max_recursion_depth(64); os->set_max_recursion_depth(64);
return os->WriteTo(&mock_); return os->WriteTo(&mock_);
} }
...@@ -270,6 +272,8 @@ class ProtostreamObjectSourceTest ...@@ -270,6 +272,8 @@ class ProtostreamObjectSourceTest
void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; } void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
void UseIntsForEnums() { use_ints_for_enums_ = true; }
void AddTrailingZeros() { add_trailing_zeros_ = true; } void AddTrailingZeros() { add_trailing_zeros_ = true; }
testing::TypeInfoTestHelper helper_; testing::TypeInfoTestHelper helper_;
...@@ -277,6 +281,7 @@ class ProtostreamObjectSourceTest ...@@ -277,6 +281,7 @@ class ProtostreamObjectSourceTest
::testing::NiceMock<MockObjectWriter> mock_; ::testing::NiceMock<MockObjectWriter> mock_;
ExpectingObjectWriter ow_; ExpectingObjectWriter ow_;
bool use_lower_camel_for_enums_; bool use_lower_camel_for_enums_;
bool use_ints_for_enums_;
bool add_trailing_zeros_; bool add_trailing_zeros_;
}; };
...@@ -498,6 +503,18 @@ TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) { ...@@ -498,6 +503,18 @@ TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
DoTest(book, Book::descriptor()); DoTest(book, Book::descriptor());
} }
TEST_P(ProtostreamObjectSourceTest, UseIntsForEnumsTest) {
Book book;
book.set_type(Book::ACTION_AND_ADVENTURE);
UseIntsForEnums();
ow_.StartObject("")
->RenderInt32("type", 3)
->EndObject();
DoTest(book, Book::descriptor());
}
TEST_P(ProtostreamObjectSourceTest, UnknownEnum) { TEST_P(ProtostreamObjectSourceTest, UnknownEnum) {
Proto3Message message; Proto3Message message;
message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234)); message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
......
...@@ -79,6 +79,7 @@ util::Status BinaryToJsonStream(TypeResolver* resolver, ...@@ -79,6 +79,7 @@ util::Status BinaryToJsonStream(TypeResolver* resolver,
google::protobuf::Type type; google::protobuf::Type type;
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);
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);
......
...@@ -61,9 +61,13 @@ struct JsonPrintOptions { ...@@ -61,9 +61,13 @@ struct JsonPrintOptions {
// set to 0 will be omitted. Set this flag to true will override the default // set to 0 will be omitted. Set this flag to true will override the default
// behavior and print primitive fields regardless of their values. // behavior and print primitive fields regardless of their values.
bool always_print_primitive_fields; bool always_print_primitive_fields;
// Whether to always print enums as ints. By default they are rendered as
// strings.
bool always_print_enums_as_ints;
JsonPrintOptions() : add_whitespace(false), JsonPrintOptions() : add_whitespace(false),
always_print_primitive_fields(false) { always_print_primitive_fields(false),
always_print_enums_as_ints(false) {
} }
}; };
......
...@@ -160,6 +160,29 @@ TEST_F(JsonUtilTest, TestDefaultValues) { ...@@ -160,6 +160,29 @@ TEST_F(JsonUtilTest, TestDefaultValues) {
ToJson(m, options)); ToJson(m, options));
} }
TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
TestMessage orig;
orig.set_enum_value(proto3::EnumType::BAR);
orig.add_repeated_enum_value(proto3::EnumType::FOO);
orig.add_repeated_enum_value(proto3::EnumType::BAR);
JsonPrintOptions print_options;
print_options.always_print_enums_as_ints = true;
string expected_json =
"{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}";
EXPECT_EQ(expected_json, ToJson(orig, print_options));
TestMessage parsed;
JsonParseOptions parse_options;
ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
EXPECT_EQ(proto3::EnumType::BAR, parsed.enum_value());
EXPECT_EQ(2, parsed.repeated_enum_value_size());
EXPECT_EQ(proto3::EnumType::FOO, parsed.repeated_enum_value(0));
EXPECT_EQ(proto3::EnumType::BAR, parsed.repeated_enum_value(1));
}
TEST_F(JsonUtilTest, ParseMessage) { TEST_F(JsonUtilTest, ParseMessage) {
// Some random message but good enough to verify that the parsing warpper // Some random message but good enough to verify that the parsing warpper
// functions are working properly. // functions are working properly.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment