diff options
Diffstat (limited to 'src/google/protobuf/util')
9 files changed, 112 insertions, 4 deletions
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h index 28496963..f2b4f42f 100644 --- a/src/google/protobuf/util/internal/proto_writer.h +++ b/src/google/protobuf/util/internal/proto_writer.h @@ -110,7 +110,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { return RenderDataPiece(name, DataPiece(value, use_strict_base64_decoding())); } - virtual ProtoWriter* RenderBytes(StringPiece name, StringPiece value) { + ProtoWriter* RenderBytes(StringPiece name, StringPiece value) override { return RenderDataPiece( name, DataPiece(value, false, use_strict_base64_decoding())); } diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 56e6db12..b0d86c17 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -648,6 +648,13 @@ Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, // using a nested ProtoStreamObjectSource using our nested type information. ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type); + // TODO(htuch): This is somewhat fragile, since new options may be omitted. + // We should probably do this via the constructor or some object grouping + // options. + nested_os.set_use_lower_camel_for_enums(os->use_lower_camel_for_enums_); + nested_os.set_use_ints_for_enums(os->use_ints_for_enums_); + nested_os.set_preserve_proto_field_names(os->preserve_proto_field_names_); + // We manually call start and end object here so we can inject the @type. ow->StartObject(field_name); ow->RenderString("@type", type_url); diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc index df790728..4d86b856 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -100,6 +100,7 @@ class ProtostreamObjectSourceTest ow_(&mock_), use_lower_camel_for_enums_(false), use_ints_for_enums_(false), + use_preserve_proto_field_names_(false), add_trailing_zeros_(false), render_unknown_enum_values_(true) { helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor()); @@ -123,6 +124,7 @@ class ProtostreamObjectSourceTest helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); 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); + if (use_preserve_proto_field_names_) os->set_preserve_proto_field_names(true); os->set_max_recursion_depth(64); return os->WriteTo(&mock_); } @@ -272,6 +274,8 @@ class ProtostreamObjectSourceTest void UseIntsForEnums() { use_ints_for_enums_ = true; } + void UsePreserveProtoFieldNames() { use_preserve_proto_field_names_ = true; } + void AddTrailingZeros() { add_trailing_zeros_ = true; } void SetRenderUnknownEnumValues(bool value) { @@ -284,6 +288,7 @@ class ProtostreamObjectSourceTest ExpectingObjectWriter ow_; bool use_lower_camel_for_enums_; bool use_ints_for_enums_; + bool use_preserve_proto_field_names_; bool add_trailing_zeros_; bool render_unknown_enum_values_; }; @@ -536,6 +541,16 @@ TEST_P(ProtostreamObjectSourceTest, UseIntsForEnumsTest) { DoTest(book, Book::descriptor()); } +TEST_P(ProtostreamObjectSourceTest, UsePreserveProtoFieldNames) { + Book book; + book.set_snake_field("foo"); + + UsePreserveProtoFieldNames(); + + ow_.StartObject("")->RenderString("snake_field", "foo")->EndObject(); + DoTest(book, Book::descriptor()); +} + TEST_P(ProtostreamObjectSourceTest, UnknownEnumAreDroppedWhenRenderUnknownEnumValuesIsUnset) { Proto3Message message; @@ -769,6 +784,69 @@ TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) { DoTest(out, AnyOut::descriptor()); } +TEST_P(ProtostreamObjectSourceAnysTest, LowerCamelEnumOutputSnakeCase) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + Book book; + book.set_type(Book::arts_and_photography); + any->PackFrom(book); + + UseLowerCamelForEnums(); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.Book") + ->RenderString("type", "artsAndPhotography") + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, UseIntsForEnumsTest) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + Book book; + book.set_type(Book::ACTION_AND_ADVENTURE); + any->PackFrom(book); + + UseIntsForEnums(); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.Book") + ->RenderInt32("type", 3) + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, UsePreserveProtoFieldNames) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + Book book; + book.set_snake_field("foo"); + any->PackFrom(book); + + UsePreserveProtoFieldNames(); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.Book") + ->RenderString("snake_field", "foo") + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) { AnyOut out; ::google::protobuf::Any* any = out.mutable_any(); diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 2edfd075..a1a7030a 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -534,7 +534,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( Push("", Item::MESSAGE, false, false); ProtoWriter::RenderDataPiece("key", DataPiece(name, use_strict_base64_decoding())); - Push("value", Item::MESSAGE, true, false); + Push("value", IsAny(*Lookup("value")) ? Item::ANY : Item::MESSAGE, true, false); // Make sure we are valid so far after starting map fields. if (invalid_depth() > 0) return this; diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index 7f0df567..9c50e7dd 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -1679,6 +1679,22 @@ TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) { ->EndObject(); } +TEST_P(ProtoStreamObjectWriterMapTest, AnyInMap) { + MapIn mm; + google::protobuf::DoubleValue d; + d.set_value(40.2); + (*mm.mutable_map_any())["foo"].PackFrom(d); + ow_->StartObject("") + ->StartObject("map_any") + ->StartObject("foo") + ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue") + ->RenderDouble("value", 40.2) + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(mm); +} + class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest { protected: ProtoStreamObjectWriterAnyTest() { diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto index 5630cc78..5e08a291 100644 --- a/src/google/protobuf/util/internal/testdata/books.proto +++ b/src/google/protobuf/util/internal/testdata/books.proto @@ -69,6 +69,9 @@ message Book { } optional Type type = 11; + // Useful for testing JSON snake/camel-case conversions. + optional string snake_field = 12; + extensions 200 to 499; } diff --git a/src/google/protobuf/util/internal/testdata/maps.proto b/src/google/protobuf/util/internal/testdata/maps.proto index 0f381b32..765254ea 100644 --- a/src/google/protobuf/util/internal/testdata/maps.proto +++ b/src/google/protobuf/util/internal/testdata/maps.proto @@ -32,6 +32,8 @@ syntax = "proto3"; package google.protobuf.testing; +import "google/protobuf/any.proto"; + // Top-level test cases proto used by MarshallingTest. See description // at the top of the class MarshallingTest for details on how to write // test cases. @@ -103,6 +105,7 @@ message MapIn { string other = 1; repeated string things = 2; map<string, string> map_input = 3; + map<string, google.protobuf.Any> map_any = 4; } message MapOut { diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc index f81a7a30..9ad073d8 100644 --- a/src/google/protobuf/util/json_util.cc +++ b/src/google/protobuf/util/json_util.cc @@ -127,7 +127,8 @@ class StatusErrorListener : public converter::ErrorListener { virtual void InvalidName(const converter::LocationTrackerInterface& loc, StringPiece unknown_name, StringPiece message) { status_ = util::Status(util::error::INVALID_ARGUMENT, - loc.ToString() + ": " + string(message)); + loc.ToString() + ": invalid name " + + string(unknown_name) + ": " + string(message)); } virtual void InvalidValue(const converter::LocationTrackerInterface& loc, diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index ed9092df..a2a84b57 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -284,7 +284,7 @@ TEST_F(JsonUtilTest, ParsePrimitiveMapIn) { JsonPrintOptions print_options; print_options.always_print_primitive_fields = true; JsonParseOptions parse_options; - EXPECT_EQ("{\"other\":\"\",\"things\":[],\"mapInput\":{}}", + EXPECT_EQ("{\"other\":\"\",\"things\":[],\"mapInput\":{},\"mapAny\":{}}", ToJson(message, print_options)); MapIn other; ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options)); |