diff options
author | Lizan Zhou <zlizan@google.com> | 2016-06-22 11:46:10 -0700 |
---|---|---|
committer | Lizan Zhou <zlizan@google.com> | 2016-06-28 00:17:06 -0700 |
commit | 31999a3f95d8ec9f93b56b0966e2895c5205da53 (patch) | |
tree | b6b430749dd1af0444b1de5a90682bf26716341a /src/google/protobuf/util/internal | |
parent | dc0aeaa9030bdac264b44d56d07b6839a1ae94e9 (diff) |
Add JsonParseOptions to ignore unknown fields
- add JsonParseOptions for JsonToBinaryString allow unknown fields
- rename current JsonOptions to JsonPrintOptions
Diffstat (limited to 'src/google/protobuf/util/internal')
5 files changed, 140 insertions, 4 deletions
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc index 36b79410..052a0c96 100644 --- a/src/google/protobuf/util/internal/proto_writer.cc +++ b/src/google/protobuf/util/internal/proto_writer.cc @@ -71,6 +71,7 @@ ProtoWriter::ProtoWriter(TypeResolver* type_resolver, adapter_(&buffer_), stream_(new CodedOutputStream(&adapter_)), listener_(listener), + ignore_unknown_fields_(false), invalid_depth_(0), tracker_(new ObjectLocationTracker()) {} @@ -88,6 +89,7 @@ ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, adapter_(&buffer_), stream_(new CodedOutputStream(&adapter_)), listener_(listener), + ignore_unknown_fields_(false), invalid_depth_(0), tracker_(new ObjectLocationTracker()) {} @@ -692,7 +694,9 @@ const google::protobuf::Field* ProtoWriter::Lookup( } const google::protobuf::Field* field = typeinfo_->FindField(&e->type(), unnormalized_name); - if (field == NULL) InvalidName(unnormalized_name, "Cannot find field."); + if (field == NULL && !ignore_unknown_fields_) { + InvalidName(unnormalized_name, "Cannot find field."); + } return field; } diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h index 957565e7..6f276065 100644 --- a/src/google/protobuf/util/internal/proto_writer.h +++ b/src/google/protobuf/util/internal/proto_writer.h @@ -142,6 +142,10 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { const TypeInfo* typeinfo() { return typeinfo_; } + void set_ignore_unknown_fields(bool ignore_unknown_fields) { + ignore_unknown_fields_ = ignore_unknown_fields; + } + protected: class LIBPROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface { public: @@ -240,7 +244,8 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // Lookup the field in the current element. Looks in the base descriptor // and in any extension. This will report an error if the field cannot be - // found or if multiple matching extensions are found. + // found when ignore_unknown_names_ is false or if multiple matching + // extensions are found. const google::protobuf::Field* Lookup(StringPiece name); // Lookup the field type in the type descriptor. Returns NULL if the type @@ -293,6 +298,9 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // Indicates whether we finished writing root message completely. bool done_; + // If true, don't report unknown field names to the listener. + bool ignore_unknown_fields_; + // Variable for internal state processing: // element_ : the current element. // size_insert_: sizes of nested messages. diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 97a7909a..a6de246d 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -63,7 +63,9 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter( : ProtoWriter(type_resolver, type, output, listener), master_type_(type), current_(NULL), - options_(options) {} + options_(options) { + set_ignore_unknown_fields(options_.ignore_unknown_fields); +} ProtoStreamObjectWriter::ProtoStreamObjectWriter( const TypeInfo* typeinfo, const google::protobuf::Type& type, diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index e1162d43..8043bb3b 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -83,7 +83,12 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // preserve integer precision. bool struct_integers_as_strings; - Options() : struct_integers_as_strings(false) {} + // Not treat unknown fields as an error. If there is an unknown fields, + // just ignore it and continue to process the rest. + bool ignore_unknown_fields; + + Options() + : struct_integers_as_strings(false), ignore_unknown_fields(false) {} // Default instance of Options with all options set to defaults. static const Options& Defaults() { diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index 9a0dcde1..30e58e62 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -183,6 +183,10 @@ class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest { ProtoStreamObjectWriterTest() : BaseProtoStreamObjectWriterTest(Book::descriptor()) {} + void ResetProtoWriter() { + ResetTypeInfo(Book::descriptor()); + } + virtual ~ProtoStreamObjectWriterTest() {} }; @@ -709,6 +713,119 @@ TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) { CheckOutput(expected); } +TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtRoot) { + Book empty; + + options_.ignore_unknown_fields = true; + ResetProtoWriter(); + + EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); + ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtAuthorFriend) { + Book expected; + Author* paul = expected.mutable_author(); + paul->set_name("Paul"); + Author* mark = paul->add_friend_(); + mark->set_name("Mark"); + Author* john = paul->add_friend_(); + john->set_name("John"); + Author* luke = paul->add_friend_(); + luke->set_name("Luke"); + + options_.ignore_unknown_fields = true; + ResetProtoWriter(); + + EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "Paul") + ->StartList("friend") + ->StartObject("") + ->RenderString("name", "Mark") + ->EndObject() + ->StartObject("") + ->RenderString("name", "John") + ->RenderString("address", "Patmos") + ->EndObject() + ->StartObject("") + ->RenderString("name", "Luke") + ->EndObject() + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtRoot) { + Book empty; + + options_.ignore_unknown_fields = true; + ResetProtoWriter(); + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), + StringPiece("Cannot find field."))) + .Times(0); + ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtAuthor) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("William"); + author->add_pseudonym("Bill"); + + options_.ignore_unknown_fields = true; + ResetProtoWriter(); + + EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "William") + ->StartObject("wife") + ->RenderString("name", "Hilary") + ->EndObject() + ->RenderString("pseudonym", "Bill") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtRoot) { + Book empty; + + options_.ignore_unknown_fields = true; + ResetProtoWriter(); + + EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); + ow_->StartObject("")->StartList("unknown")->EndList()->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtPublisher) { + Book expected; + expected.set_title("Brainwashing"); + Publisher* publisher = expected.mutable_publisher(); + publisher->set_name("propaganda"); + + options_.ignore_unknown_fields = true; + ResetProtoWriter(); + + EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); + ow_->StartObject("") + ->StartObject("publisher") + ->RenderString("name", "propaganda") + ->StartList("alliance") + ->EndList() + ->EndObject() + ->RenderString("title", "Brainwashing") + ->EndObject(); + CheckOutput(expected); +} + TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) { Book expected; expected.set_title("My Title"); |