aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/util/internal
diff options
context:
space:
mode:
authorGravatar Feng Xiao <xiaofeng@google.com>2016-07-01 15:43:37 -0700
committerGravatar GitHub <noreply@github.com>2016-07-01 15:43:37 -0700
commitcae3b0cbb689d0ed1e5da73942a5a9705f3411b0 (patch)
tree855f5c2c2d2dd82715145401ed68d20ff025693c /src/google/protobuf/util/internal
parent02b55d248f2fa9f24905201d1ba16a79dd20fdc8 (diff)
parent31999a3f95d8ec9f93b56b0966e2895c5205da53 (diff)
Merge pull request #1704 from lizan/json_parse_options
Add JsonParseOptions to ignore unknown fields
Diffstat (limited to 'src/google/protobuf/util/internal')
-rw-r--r--src/google/protobuf/util/internal/proto_writer.cc6
-rw-r--r--src/google/protobuf/util/internal/proto_writer.h10
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc4
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.h7
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter_test.cc117
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 18cc1233..3e09c9bb 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()) {}
@@ -702,7 +704,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 ffb8f60e..da121809 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -143,6 +143,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:
@@ -244,7 +248,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
@@ -297,6 +302,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 8fa58a6f..1825f556 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 75e3d67d..2e4d14d1 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");