The JsonParseOptions::ignore_unknown_fields option behavior treats

unrecognized string values in enum fields as default ones.
pull/4195/head
Alexey Malov 7 years ago committed by Alexey Malov
parent 47b7d2c7ca
commit 02452db725
  1. 7
      src/google/protobuf/util/internal/datapiece.cc
  2. 3
      src/google/protobuf/util/internal/datapiece.h
  3. 8
      src/google/protobuf/util/internal/proto_writer.cc
  4. 2
      src/google/protobuf/util/internal/proto_writer.h
  5. 58
      src/google/protobuf/util/json_util_test.cc

@ -272,7 +272,8 @@ StatusOr<string> DataPiece::ToBytes() const {
}
StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
bool use_lower_camel_for_enums) const {
bool use_lower_camel_for_enums,
bool ignore_unknown_enum_values) const {
if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;
if (type_ == TYPE_STRING) {
@ -305,6 +306,10 @@ StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
value = FindEnumValueByNameWithoutUnderscoreOrNull(enum_type, enum_name);
if (value != NULL) return value->number();
}
// If ignore_unknown_enum_values is true an unknown enum value is treated
// as the default
if (ignore_unknown_enum_values) return enum_type->enumvalue(0).number();
} else {
// We don't need to check whether the value is actually declared in the
// enum because we preserve unknown enum values as well.

@ -164,7 +164,8 @@ class LIBPROTOBUF_EXPORT DataPiece {
// If the value is not a string, attempts to convert to a 32-bit integer.
// If none of these succeeds, returns a conversion error status.
util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type,
bool use_lower_camel_for_enums) const;
bool use_lower_camel_for_enums,
bool ignore_unknown_enum_values) const;
private:
// Disallow implicit constructor.

@ -267,8 +267,9 @@ inline Status WriteString(int field_number, const DataPiece& data,
inline Status WriteEnum(int field_number, const DataPiece& data,
const google::protobuf::Enum* enum_type,
CodedOutputStream* stream,
bool use_lower_camel_for_enums) {
StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums);
bool use_lower_camel_for_enums,
bool ignore_unknown_values) {
StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums, ignore_unknown_values);
if (e.ok()) {
WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream);
}
@ -665,7 +666,8 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField(
case google::protobuf::Field_Kind_TYPE_ENUM: {
status = WriteEnum(field.number(), data,
typeinfo_->GetEnumByTypeUrl(field.type_url()),
stream_.get(), use_lower_camel_for_enums_);
stream_.get(), use_lower_camel_for_enums_,
ignore_unknown_fields_);
break;
}
default: // TYPE_GROUP or TYPE_MESSAGE

@ -309,7 +309,7 @@ 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.
// If true, don't report unknown field names and enum values to the listener.
bool ignore_unknown_fields_;
// If true, check if enum name in camel case or without underscore matches the

@ -333,6 +333,64 @@ TEST_F(JsonUtilTest, TestDynamicMessage) {
EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
}
TEST_F(JsonUtilTest, TestParsingUnknownEnumsAs0) {
TestMessage m;
{
JsonParseOptions options;
ASSERT_FALSE(options.ignore_unknown_fields);
string input =
"{\n"
" \"enum_value\":\"UNKNOWN_VALUE\"\n"
"}";
m.set_enum_value(proto3::BAR);
EXPECT_FALSE(FromJson(input, &m, options));
ASSERT_EQ(proto3::BAR, m.enum_value()); // Keep previous value
options.ignore_unknown_fields = true;
EXPECT_TRUE(FromJson(input, &m, options));
EXPECT_EQ(0, m.enum_value()); // Unknown enum value must be decoded as 0
}
// Integer values are read as usual
{
JsonParseOptions options;
string input =
"{\n"
" \"enum_value\":12345\n"
"}";
m.set_enum_value(proto3::BAR);
EXPECT_TRUE(FromJson(input, &m, options));
ASSERT_EQ(12345, m.enum_value());
options.ignore_unknown_fields = true;
EXPECT_TRUE(FromJson(input, &m, options));
EXPECT_EQ(12345, m.enum_value());
}
// Trying to pass an object as an enum field value is always treated as an error
{
JsonParseOptions options;
string input =
"{\n"
" \"enum_value\":{}\n"
"}";
options.ignore_unknown_fields = true;
EXPECT_FALSE(FromJson(input, &m, options));
options.ignore_unknown_fields = false;
EXPECT_FALSE(FromJson(input, &m, options));
}
// Trying to pass an array as an enum field value is always treated as an error
{
JsonParseOptions options;
string input =
"{\n"
" \"enum_value\":[]\n"
"}";
EXPECT_FALSE(FromJson(input, &m, options));
options.ignore_unknown_fields = true;
EXPECT_FALSE(FromJson(input, &m, options));
}
}
typedef std::pair<char*, int> Segment;
// A ZeroCopyOutputStream that writes to multiple buffers.
class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {

Loading…
Cancel
Save