Commit 02452db7 authored by Alexey Malov's avatar Alexey Malov Committed by Alexey Malov

The JsonParseOptions::ignore_unknown_fields option behavior treats

unrecognized string values in enum fields as default ones.
parent 47b7d2c7
......@@ -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 {
......
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