From 26eeec93e44024ee10c0b8c536ea2410e4bfa7f3 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Mon, 9 Jul 2018 14:29:23 -0700 Subject: Enable ignoring unknown in json parsing in php (#4839) * Enable ignoring unknown in json parsing in php * Update generated descriptor files * Update failure list for other languages. * Remove unnecessary php files --- conformance/conformance.proto | 2 + conformance/conformance_php.php | 8 +- conformance/conformance_test.cc | 246 ++++++++++++++------- conformance/conformance_test.h | 59 +++-- conformance/failure_list_cpp.txt | 6 + conformance/failure_list_csharp.txt | 6 + conformance/failure_list_java.txt | 6 + conformance/failure_list_php_c.txt | 56 ----- conformance/failure_list_python-post26.txt | 6 + conformance/failure_list_python.txt | 6 + conformance/failure_list_python_cpp.txt | 6 + conformance/failure_list_ruby.txt | 6 + .../src/Google.Protobuf.Conformance/Conformance.cs | 47 +++- php/ext/google/protobuf/encode_decode.c | 7 +- php/ext/google/protobuf/upb.c | 128 +++++++---- php/ext/google/protobuf/upb.h | 9 +- 16 files changed, 386 insertions(+), 218 deletions(-) diff --git a/conformance/conformance.proto b/conformance/conformance.proto index 525140e9..897e7b38 100644 --- a/conformance/conformance.proto +++ b/conformance/conformance.proto @@ -82,6 +82,8 @@ message ConformanceRequest { // protobuf_test_messages.proto3.TestAllTypesProto3 or // protobuf_test_messages.proto2.TestAllTypesProto2. string message_type = 4; + + bool ignore_unknown_json = 5; } // Represents a single test case's output. diff --git a/conformance/conformance_php.php b/conformance/conformance_php.php index 19f9a092..65483e27 100755 --- a/conformance/conformance_php.php +++ b/conformance/conformance_php.php @@ -6,8 +6,8 @@ require_once("Conformance/ConformanceRequest.php"); require_once("Protobuf_test_messages/Proto3/ForeignMessage.php"); require_once("Protobuf_test_messages/Proto3/ForeignEnum.php"); require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php"); -require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedMessage.php"); -require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedEnum.php"); +require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedMessage.php"); +require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedEnum.php"); require_once("GPBMetadata/Conformance.php"); require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php"); @@ -39,8 +39,10 @@ function doTest($request) trigger_error("Protobuf request doesn't have specific payload type", E_USER_ERROR); } } elseif ($request->getPayload() == "json_payload") { + $ignore_json_unknown = $request->getIgnoreUnknownJson(); try { - $test_message->mergeFromJsonString($request->getJsonPayload()); + $test_message->mergeFromJsonString($request->getJsonPayload(), + $ignore_json_unknown); } catch (Exception $e) { $response->setParseError($e->getMessage()); return $response; diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc index 22bbbfb3..d9e88ce5 100644 --- a/conformance/conformance_test.cc +++ b/conformance/conformance_test.cc @@ -191,6 +191,78 @@ string UpperCase(string str) { namespace google { namespace protobuf { +ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting( + ConformanceLevel level, conformance::WireFormat input_format, + conformance::WireFormat output_format, bool is_proto3, + const string& test_name, const string& input) + : level_(level), input_format_(input_format), + output_format_(output_format), is_proto3_(is_proto3) { + auto newTestMessage = [&is_proto3]() { + Message* newMessage; + if (is_proto3) { + newMessage = new TestAllTypesProto3; + } else { + newMessage = new TestAllTypesProto2; + } + return newMessage; + }; + + string input_format_string; + string output_format_string; + string rname = is_proto3 ? ".Proto3" : ".Proto2"; + + switch (input_format) { + case conformance::PROTOBUF: { + request_.set_protobuf_payload(input); + input_format_string = ".ProtobufInput."; + break; + } + + case conformance::JSON: { + request_.set_json_payload(input); + input_format_string = ".JsonInput."; + break; + } + + default: + GOOGLE_LOG(FATAL) << "Unspecified input format"; + } + + switch (output_format) { + case conformance::PROTOBUF: { + output_format_string = ".ProtobufOutput"; + break; + } + + case conformance::JSON: { + output_format_string = ".JsonOutput"; + break; + } + + default: + GOOGLE_LOG(FATAL) << "Unspecified output format"; + } + + test_name_ = ConformanceLevelToString(level) + rname + + input_format_string + test_name + + output_format_string; + + if (is_proto3) { + request_.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); + } else { + request_.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2"); + } + request_.set_requested_output_format(output_format); +} + +Message* ConformanceTestSuite::ConformanceRequestSetting::GetTestMessage() const { + if (is_proto3_) { + return new TestAllTypesProto3(); + } else { + return new TestAllTypesProto2(); + } +} + void ConformanceTestSuite::ReportSuccess(const string& test_name) { if (expected_to_fail_.erase(test_name) != 0) { StringAppendF(&output_, @@ -273,75 +345,36 @@ void ConformanceTestSuite::RunTest(const string& test_name, } void ConformanceTestSuite::RunValidInputTest( - const string& test_name, ConformanceLevel level, const string& input, - WireFormat input_format, const string& equivalent_text_format, - WireFormat requested_output, bool isProto3) { - auto newTestMessage = [&isProto3]() { - Message* newMessage; - if (isProto3) { - newMessage = new TestAllTypesProto3; - } else { - newMessage = new TestAllTypesProto2; - } - return newMessage; - }; - Message* reference_message = newTestMessage(); + const ConformanceRequestSetting& setting, + const string& equivalent_text_format) { + Message* reference_message = setting.GetTestMessage(); GOOGLE_CHECK( TextFormat::ParseFromString(equivalent_text_format, reference_message)) - << "Failed to parse data for test case: " << test_name + << "Failed to parse data for test case: " << setting.GetTestName() << ", data: " << equivalent_text_format; const string equivalent_wire_format = reference_message->SerializeAsString(); - RunValidBinaryInputTest(test_name, level, input, input_format, - equivalent_wire_format, requested_output, isProto3); + RunValidBinaryInputTest(setting, equivalent_wire_format); } void ConformanceTestSuite::RunValidBinaryInputTest( - const string& test_name, ConformanceLevel level, const string& input, - WireFormat input_format, const string& equivalent_wire_format, - WireFormat requested_output, bool isProto3) { - auto newTestMessage = [&isProto3]() { - Message* newMessage; - if (isProto3) { - newMessage = new TestAllTypesProto3; - } else { - newMessage = new TestAllTypesProto2; - } - return newMessage; - }; - Message* reference_message = newTestMessage(); + const ConformanceRequestSetting& setting, + const string& equivalent_wire_format) { + const string& test_name = setting.GetTestName(); + ConformanceLevel level = setting.GetLevel(); + + Message* reference_message = setting.GetTestMessage(); GOOGLE_CHECK( reference_message->ParseFromString(equivalent_wire_format)) << "Failed to parse wire data for test case: " << test_name; - ConformanceRequest request; + const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - switch (input_format) { - case conformance::PROTOBUF: { - request.set_protobuf_payload(input); - if (isProto3) { - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - } else { - request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2"); - } - break; - } - - case conformance::JSON: { - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - request.set_json_payload(input); - break; - } - - default: - GOOGLE_LOG(FATAL) << "Unspecified input format"; - } - - request.set_requested_output_format(requested_output); - RunTest(test_name, request, &response); - Message *test_message = newTestMessage(); + Message* test_message = setting.GetTestMessage(); + + WireFormat requested_output = request.requested_output_format(); switch (response.result_case()) { case ConformanceResponse::RESULT_NOT_SET: @@ -476,56 +509,60 @@ void ConformanceTestSuite::ExpectHardParseFailureForProto( void ConformanceTestSuite::RunValidJsonTest( const string& test_name, ConformanceLevel level, const string& input_json, const string& equivalent_text_format) { - RunValidInputTest( - ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name + - ".ProtobufOutput", level, input_json, conformance::JSON, - equivalent_text_format, conformance::PROTOBUF, true); - RunValidInputTest( - ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name + - ".JsonOutput", level, input_json, conformance::JSON, - equivalent_text_format, conformance::JSON, true); + ConformanceRequestSetting setting1( + level, conformance::JSON, conformance::PROTOBUF, + true, test_name, input_json); + RunValidInputTest(setting1, equivalent_text_format); + + ConformanceRequestSetting setting2( + level, conformance::JSON, conformance::JSON, + true, test_name, input_json); + RunValidInputTest(setting2, equivalent_text_format); } void ConformanceTestSuite::RunValidJsonTestWithProtobufInput( const string& test_name, ConformanceLevel level, const TestAllTypesProto3& input, const string& equivalent_text_format) { - RunValidInputTest( - ConformanceLevelToString(level) + ".Proto3" + ".ProtobufInput." + test_name + - ".JsonOutput", level, input.SerializeAsString(), conformance::PROTOBUF, - equivalent_text_format, conformance::JSON, true); + ConformanceRequestSetting setting( + level, conformance::PROTOBUF, conformance::JSON, + true, test_name, input.SerializeAsString()); + RunValidInputTest(setting, equivalent_text_format); +} + +void ConformanceTestSuite::RunValidJsonIgnoreUnknownTest( + const string& test_name, ConformanceLevel level, const string& input_json, + const string& equivalent_text_format) { + ConformanceRequestSetting setting( + level, conformance::JSON, conformance::PROTOBUF, + true, test_name, input_json); + setting.SetIgnoreUnknownJson(true); + RunValidInputTest(setting, equivalent_text_format); } void ConformanceTestSuite::RunValidProtobufTest( const string& test_name, ConformanceLevel level, const string& input_protobuf, const string& equivalent_text_format, bool isProto3) { - string rname = ".Proto3"; - if (!isProto3) { - rname = ".Proto2"; - } - RunValidInputTest( - ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name + - ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF, - equivalent_text_format, conformance::PROTOBUF, isProto3); + ConformanceRequestSetting setting1( + level, conformance::PROTOBUF, conformance::PROTOBUF, + isProto3, test_name, input_protobuf); + RunValidInputTest(setting1, equivalent_text_format); + if (isProto3) { - RunValidInputTest( - ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name + - ".JsonOutput", level, input_protobuf, conformance::PROTOBUF, - equivalent_text_format, conformance::JSON, isProto3); + ConformanceRequestSetting setting2( + level, conformance::PROTOBUF, conformance::JSON, + true, test_name, input_protobuf); + RunValidInputTest(setting2, equivalent_text_format); } } void ConformanceTestSuite::RunValidBinaryProtobufTest( const string& test_name, ConformanceLevel level, const string& input_protobuf, bool isProto3) { - string rname = ".Proto3"; - if (!isProto3) { - rname = ".Proto2"; - } - RunValidBinaryInputTest( - ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name + - ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF, - input_protobuf, conformance::PROTOBUF, isProto3); + ConformanceRequestSetting setting( + level, conformance::PROTOBUF, conformance::PROTOBUF, + isProto3, test_name, input_protobuf); + RunValidBinaryInputTest(setting, input_protobuf); } void ConformanceTestSuite::RunValidProtobufTestWithMessage( @@ -2535,6 +2572,43 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, } )"); + RunValidJsonIgnoreUnknownTest( + "IgnoreUnknownJsonNumber", REQUIRED, + R"({ + "unknown": 1 + })", + ""); + RunValidJsonIgnoreUnknownTest( + "IgnoreUnknownJsonString", REQUIRED, + R"({ + "unknown": "a" + })", + ""); + RunValidJsonIgnoreUnknownTest( + "IgnoreUnknownJsonTrue", REQUIRED, + R"({ + "unknown": true + })", + ""); + RunValidJsonIgnoreUnknownTest( + "IgnoreUnknownJsonFalse", REQUIRED, + R"({ + "unknown": false + })", + ""); + RunValidJsonIgnoreUnknownTest( + "IgnoreUnknownJsonNull", REQUIRED, + R"({ + "unknown": null + })", + ""); + RunValidJsonIgnoreUnknownTest( + "IgnoreUnknownJsonObject", REQUIRED, + R"({ + "unknown": {"a": 1} + })", + ""); + bool ok = true; if (!CheckSetEmpty(expected_to_fail_, "nonexistent_tests.txt", "These tests were listed in the failure list, but they " diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h index 2649f8b2..685f67fb 100644 --- a/conformance/conformance_test.h +++ b/conformance/conformance_test.h @@ -44,6 +44,7 @@ #include #include +#include "conformance.pb.h" #include "third_party/jsoncpp/json.h" namespace conformance { @@ -146,7 +147,42 @@ class ConformanceTestSuite { REQUIRED = 0, RECOMMENDED = 1, }; - string ConformanceLevelToString(ConformanceLevel level); + + class ConformanceRequestSetting { + public: + ConformanceRequestSetting( + ConformanceLevel level, conformance::WireFormat input_format, + conformance::WireFormat output_format, bool is_proto3, + const string& test_name, const string& input); + + Message* GetTestMessage() const; + + const string& GetTestName() const { + return test_name_; + } + + const conformance::ConformanceRequest& GetRequest() const { + return request_; + } + + const ConformanceLevel GetLevel() const { + return level_; + } + + void SetIgnoreUnknownJson(bool ignore_unknown_json) { + request_.set_ignore_unknown_json(ignore_unknown_json); + } + + private: + ConformanceLevel level_; + conformance::WireFormat input_format_; + conformance::WireFormat output_format_; + bool is_proto3_; + string test_name_; + conformance::ConformanceRequest request_; + }; + + static string ConformanceLevelToString(ConformanceLevel level); void ReportSuccess(const std::string& test_name); void ReportFailure(const string& test_name, @@ -160,24 +196,17 @@ class ConformanceTestSuite { void RunTest(const std::string& test_name, const conformance::ConformanceRequest& request, conformance::ConformanceResponse* response); - void RunValidInputTest(const string& test_name, - ConformanceLevel level, - const string& input, - conformance::WireFormat input_format, - const string& equivalent_text_format, - conformance::WireFormat requested_output, - bool isProto3); - void RunValidBinaryInputTest(const string& test_name, - ConformanceLevel level, - const string& input, - conformance::WireFormat input_format, - const string& equivalent_wire_format, - conformance::WireFormat requested_output, - bool isProto3); + void RunValidInputTest(const ConformanceRequestSetting& setting, + const string& equivalent_text_format); + void RunValidBinaryInputTest(const ConformanceRequestSetting& setting, + const string& equivalent_wire_format); void RunValidJsonTest(const string& test_name, ConformanceLevel level, const string& input_json, const string& equivalent_text_format); + void RunValidJsonIgnoreUnknownTest( + const string& test_name, ConformanceLevel level, const string& input_json, + const string& equivalent_text_format); void RunValidJsonTestWithProtobufInput( const string& test_name, ConformanceLevel level, diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt index 752fbb5d..ea8e8473 100644 --- a/conformance/failure_list_cpp.txt +++ b/conformance/failure_list_cpp.txt @@ -54,3 +54,9 @@ Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32 Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64 Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32 Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64 +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt index 2a20aa78..69c723b5 100644 --- a/conformance/failure_list_csharp.txt +++ b/conformance/failure_list_csharp.txt @@ -1,2 +1,8 @@ Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt index dc1f9ba5..6f085c66 100644 --- a/conformance/failure_list_java.txt +++ b/conformance/failure_list_java.txt @@ -45,3 +45,9 @@ Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValu Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt index 088708e9..6ecd94fd 100644 --- a/conformance/failure_list_php_c.txt +++ b/conformance/failure_list_php_c.txt @@ -1,8 +1,6 @@ Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.FieldMaskPathsDontRoundTrip.JsonOutput Recommended.FieldMaskTooManyUnderscore.JsonOutput -Recommended.Proto3.JsonInput.BoolFieldIntegerOne -Recommended.Proto3.JsonInput.BoolFieldIntegerZero Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator @@ -10,9 +8,6 @@ Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator Recommended.Proto3.JsonInput.Int64FieldBeString.Validator Recommended.Proto3.JsonInput.MapFieldValueIsNull Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput -Recommended.Proto3.JsonInput.OneofZeroBytes.ProtobufOutput -Recommended.Proto3.JsonInput.OneofZeroString.JsonOutput -Recommended.Proto3.JsonInput.OneofZeroString.ProtobufOutput Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull Recommended.Proto3.JsonInput.StringEndsWithEscapeChar @@ -21,9 +16,6 @@ Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput -Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput -Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput -Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput Required.DurationProtoInputTooLarge.JsonOutput Required.DurationProtoInputTooSmall.JsonOutput Required.Proto3.JsonInput.Any.JsonOutput @@ -47,63 +39,22 @@ Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput Required.Proto3.JsonInput.BoolMapField.JsonOutput -Required.Proto3.JsonInput.DoubleFieldInfinity.JsonOutput -Required.Proto3.JsonInput.DoubleFieldInfinity.ProtobufOutput Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput -Required.Proto3.JsonInput.DoubleFieldNan.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.JsonOutput -Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldQuotedValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldQuotedValue.ProtobufOutput Required.Proto3.JsonInput.DurationMaxValue.JsonOutput Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput Required.Proto3.JsonInput.DurationMinValue.JsonOutput Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.JsonOutput -Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput -Required.Proto3.JsonInput.EnumFieldNumericValueZero.JsonOutput -Required.Proto3.JsonInput.EnumFieldNumericValueZero.ProtobufOutput -Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator Required.Proto3.JsonInput.FieldMask.JsonOutput Required.Proto3.JsonInput.FieldMask.ProtobufOutput Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput -Required.Proto3.JsonInput.FloatFieldInfinity.ProtobufOutput Required.Proto3.JsonInput.FloatFieldNan.JsonOutput -Required.Proto3.JsonInput.FloatFieldNan.ProtobufOutput Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput -Required.Proto3.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldQuotedValue.JsonOutput -Required.Proto3.JsonInput.FloatFieldQuotedValue.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldTooLarge -Required.Proto3.JsonInput.FloatFieldTooSmall -Required.Proto3.JsonInput.Int32FieldExponentialFormat.JsonOutput -Required.Proto3.JsonInput.Int32FieldExponentialFormat.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.JsonOutput -Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldMaxFloatValue.JsonOutput -Required.Proto3.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldMinFloatValue.JsonOutput -Required.Proto3.JsonInput.Int32FieldMinFloatValue.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldStringValue.JsonOutput -Required.Proto3.JsonInput.Int32FieldStringValue.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldStringValueEscaped.JsonOutput -Required.Proto3.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput -Required.Proto3.JsonInput.Int64FieldMaxValue.JsonOutput -Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput -Required.Proto3.JsonInput.Int64FieldMinValue.JsonOutput -Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput -Required.Proto3.JsonInput.MessageField.JsonOutput -Required.Proto3.JsonInput.MessageField.ProtobufOutput Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput @@ -130,8 +81,6 @@ Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput @@ -146,7 +95,6 @@ Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput Required.Proto3.JsonInput.StringFieldEscape.JsonOutput Required.Proto3.JsonInput.StringFieldEscape.ProtobufOutput -Required.Proto3.JsonInput.StringFieldNotAString Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput Required.Proto3.JsonInput.StringFieldUnicodeEscape.JsonOutput @@ -155,10 +103,6 @@ Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOu Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput Required.Proto3.JsonInput.Struct.JsonOutput Required.Proto3.JsonInput.Struct.ProtobufOutput -Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.JsonOutput -Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput -Required.Proto3.JsonInput.Uint64FieldMaxValue.JsonOutput -Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput diff --git a/conformance/failure_list_python-post26.txt b/conformance/failure_list_python-post26.txt index 19d99b04..60b1146e 100644 --- a/conformance/failure_list_python-post26.txt +++ b/conformance/failure_list_python-post26.txt @@ -1,2 +1,8 @@ JsonInput.StringFieldSurrogateInWrongOrder JsonInput.StringFieldUnpairedHighSurrogate +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt index e3ce7af7..5f01b53b 100644 --- a/conformance/failure_list_python.txt +++ b/conformance/failure_list_python.txt @@ -19,3 +19,9 @@ Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_0 Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_1 Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_2 Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_3 +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt index a498ad1a..f80517d9 100644 --- a/conformance/failure_list_python_cpp.txt +++ b/conformance/failure_list_python_cpp.txt @@ -52,3 +52,9 @@ Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32 Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64 Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32 Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64 +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt index b2683372..2d09acd4 100644 --- a/conformance/failure_list_ruby.txt +++ b/conformance/failure_list_ruby.txt @@ -135,3 +135,9 @@ Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput Required.TimestampProtoInputTooLarge.JsonOutput Required.TimestampProtoInputTooSmall.JsonOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs index f6118ea2..77284824 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -24,21 +24,22 @@ namespace Conformance { static ConformanceReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiowEKEkNvbmZvcm1h", + "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiwAEKEkNvbmZvcm1h", "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv", "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY", "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0EhQKDG1lc3NhZ2VfdHlw", - "ZRgEIAEoCUIJCgdwYXlsb2FkIrEBChNDb25mb3JtYW5jZVJlc3BvbnNlEhUK", - "C3BhcnNlX2Vycm9yGAEgASgJSAASGQoPc2VyaWFsaXplX2Vycm9yGAYgASgJ", - "SAASFwoNcnVudGltZV9lcnJvchgCIAEoCUgAEhoKEHByb3RvYnVmX3BheWxv", - "YWQYAyABKAxIABIWCgxqc29uX3BheWxvYWQYBCABKAlIABIRCgdza2lwcGVk", - "GAUgASgJSABCCAoGcmVzdWx0KjUKCldpcmVGb3JtYXQSDwoLVU5TUEVDSUZJ", - "RUQQABIMCghQUk9UT0JVRhABEggKBEpTT04QAkIhCh9jb20uZ29vZ2xlLnBy", - "b3RvYnVmLmNvbmZvcm1hbmNlYgZwcm90bzM=")); + "ZRgEIAEoCRIbChNpZ25vcmVfdW5rbm93bl9qc29uGAUgASgIQgkKB3BheWxv", + "YWQisQEKE0NvbmZvcm1hbmNlUmVzcG9uc2USFQoLcGFyc2VfZXJyb3IYASAB", + "KAlIABIZCg9zZXJpYWxpemVfZXJyb3IYBiABKAlIABIXCg1ydW50aW1lX2Vy", + "cm9yGAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgDIAEoDEgAEhYKDGpz", + "b25fcGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSABKAlIAEIICgZyZXN1", + "bHQqNQoKV2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RPQlVG", + "EAESCAoESlNPThACQiEKH2NvbS5nb29nbGUucHJvdG9idWYuY29uZm9ybWFu", + "Y2ViBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat", "MessageType" }, new[]{ "Payload" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat", "MessageType", "IgnoreUnknownJson" }, new[]{ "Payload" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null) })); } @@ -89,6 +90,7 @@ namespace Conformance { public ConformanceRequest(ConformanceRequest other) : this() { requestedOutputFormat_ = other.requestedOutputFormat_; messageType_ = other.messageType_; + ignoreUnknownJson_ = other.ignoreUnknownJson_; switch (other.PayloadCase) { case PayloadOneofCase.ProtobufPayload: ProtobufPayload = other.ProtobufPayload; @@ -158,6 +160,17 @@ namespace Conformance { } } + /// Field number for the "ignore_unknown_json" field. + public const int IgnoreUnknownJsonFieldNumber = 5; + private bool ignoreUnknownJson_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool IgnoreUnknownJson { + get { return ignoreUnknownJson_; } + set { + ignoreUnknownJson_ = value; + } + } + private object payload_; /// Enum of possible cases for the "payload" oneof. public enum PayloadOneofCase { @@ -194,6 +207,7 @@ namespace Conformance { if (JsonPayload != other.JsonPayload) return false; if (RequestedOutputFormat != other.RequestedOutputFormat) return false; if (MessageType != other.MessageType) return false; + if (IgnoreUnknownJson != other.IgnoreUnknownJson) return false; if (PayloadCase != other.PayloadCase) return false; return Equals(_unknownFields, other._unknownFields); } @@ -205,6 +219,7 @@ namespace Conformance { if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode(); if (MessageType.Length != 0) hash ^= MessageType.GetHashCode(); + if (IgnoreUnknownJson != false) hash ^= IgnoreUnknownJson.GetHashCode(); hash ^= (int) payloadCase_; if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); @@ -235,6 +250,10 @@ namespace Conformance { output.WriteRawTag(34); output.WriteString(MessageType); } + if (IgnoreUnknownJson != false) { + output.WriteRawTag(40); + output.WriteBool(IgnoreUnknownJson); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -255,6 +274,9 @@ namespace Conformance { if (MessageType.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType); } + if (IgnoreUnknownJson != false) { + size += 1 + 1; + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -272,6 +294,9 @@ namespace Conformance { if (other.MessageType.Length != 0) { MessageType = other.MessageType; } + if (other.IgnoreUnknownJson != false) { + IgnoreUnknownJson = other.IgnoreUnknownJson; + } switch (other.PayloadCase) { case PayloadOneofCase.ProtobufPayload: ProtobufPayload = other.ProtobufPayload; @@ -308,6 +333,10 @@ namespace Conformance { MessageType = input.ReadString(); break; } + case 40: { + IgnoreUnknownJson = input.ReadBool(); + break; + } } } } diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c index a8c47f4d..31a345b3 100644 --- a/php/ext/google/protobuf/encode_decode.c +++ b/php/ext/google/protobuf/encode_decode.c @@ -1587,8 +1587,11 @@ PHP_METHOD(Message, mergeFromJsonString) { char *data = NULL; PHP_PROTO_SIZE data_len; + zend_bool ignore_json_unknown = false; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &data, &data_len, + &ignore_json_unknown) == FAILURE) { return; } @@ -1607,7 +1610,7 @@ PHP_METHOD(Message, mergeFromJsonString) { stackenv_init(&se, "Error occurred during parsing: %s"); upb_sink_reset(&sink, get_fill_handlers(desc), msg); - parser = upb_json_parser_create(&se.env, method, &sink); + parser = upb_json_parser_create(&se.env, method, &sink, ignore_json_unknown); upb_bufsrc_putbuf(data, data_len, upb_json_parser_input(parser)); stackenv_uninit(&se); diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c index e01f3bfd..4644430e 100644 --- a/php/ext/google/protobuf/upb.c +++ b/php/ext/google/protobuf/upb.c @@ -14344,6 +14344,9 @@ struct upb_json_parser { /* Intermediate result of parsing a unicode escape sequence. */ uint32_t digit; + + /* Whether to proceed if unknown field is met. */ + bool ignore_json_unknown; }; struct upb_json_parsermethod { @@ -14864,6 +14867,11 @@ static bool end_number(upb_json_parser *p, const char *ptr) { return false; } + if (p->top->f == NULL) { + multipart_end(p); + return true; + } + return parse_number(p, false); } @@ -15016,6 +15024,10 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) { static bool parser_putbool(upb_json_parser *p, bool val) { bool ok; + if (p->top->f == NULL) { + return true; + } + if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { upb_status_seterrf(&p->status, "Boolean value specified for non-bool field: %s", @@ -15031,7 +15043,10 @@ static bool parser_putbool(upb_json_parser *p, bool val) { } static bool start_stringval(upb_json_parser *p) { - UPB_ASSERT(p->top->f); + if (p->top->f == NULL) { + multipart_startaccum(p); + return true; + } if (upb_fielddef_isstring(p->top->f)) { upb_jsonparser_frame *inner; @@ -15082,6 +15097,11 @@ static bool start_stringval(upb_json_parser *p) { static bool end_stringval(upb_json_parser *p) { bool ok = true; + if (p->top->f == NULL) { + multipart_end(p); + return true; + } + switch (upb_fielddef_type(p->top->f)) { case UPB_TYPE_BYTES: if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING), @@ -15273,6 +15293,10 @@ static bool handle_mapentry(upb_json_parser *p) { static bool end_membername(upb_json_parser *p) { UPB_ASSERT(!p->top->f); + if (!p->top->m) { + return true; + } + if (p->top->is_map) { return handle_mapentry(p); } else { @@ -15284,10 +15308,11 @@ static bool end_membername(upb_json_parser *p) { p->top->f = upb_value_getconstptr(v); multipart_end(p); + return true; + } else if (p->ignore_json_unknown) { + multipart_end(p); return true; } else { - /* TODO(haberman): Ignore unknown fields if requested/configured to do - * so. */ upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf); upb_env_reporterror(p->env, &p->status); return false; @@ -15319,7 +15344,18 @@ static void end_member(upb_json_parser *p) { } static bool start_subobject(upb_json_parser *p) { - UPB_ASSERT(p->top->f); + if (p->top->f == NULL) { + upb_jsonparser_frame *inner; + if (!check_stack(p)) return false; + + inner = p->top + 1; + inner->m = NULL; + inner->f = NULL; + inner->is_map = false; + inner->is_mapentry = false; + p->top = inner; + return true; + } if (upb_fielddef_ismap(p->top->f)) { upb_jsonparser_frame *inner; @@ -15378,9 +15414,12 @@ static void end_subobject(upb_json_parser *p) { upb_sink_endseq(&p->top->sink, sel); } else { upb_selector_t sel; + bool is_unknown = p->top->m == NULL; p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); - upb_sink_endsubmsg(&p->top->sink, sel); + if (!is_unknown) { + sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); + upb_sink_endsubmsg(&p->top->sink, sel); + } } } @@ -15462,11 +15501,11 @@ static void end_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 1310 "upb/json/parser.rl" +#line 1349 "upb/json/parser.rl" -#line 1222 "upb/json/parser.c" +#line 1261 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 2, 1, 3, 1, 5, 1, 6, 1, 7, 1, 8, 1, @@ -15615,7 +15654,7 @@ static const int json_en_value_machine = 27; static const int json_en_main = 1; -#line 1313 "upb/json/parser.rl" +#line 1352 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -15637,7 +15676,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 1393 "upb/json/parser.c" +#line 1432 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -15712,118 +15751,118 @@ _match: switch ( *_acts++ ) { case 0: -#line 1225 "upb/json/parser.rl" +#line 1264 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 1: -#line 1226 "upb/json/parser.rl" +#line 1265 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 10; goto _again;} } break; case 2: -#line 1230 "upb/json/parser.rl" +#line 1269 "upb/json/parser.rl" { start_text(parser, p); } break; case 3: -#line 1231 "upb/json/parser.rl" +#line 1270 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 4: -#line 1237 "upb/json/parser.rl" +#line 1276 "upb/json/parser.rl" { start_hex(parser); } break; case 5: -#line 1238 "upb/json/parser.rl" +#line 1277 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 6: -#line 1239 "upb/json/parser.rl" +#line 1278 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 7: -#line 1245 "upb/json/parser.rl" +#line 1284 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 8: -#line 1251 "upb/json/parser.rl" +#line 1290 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 9: -#line 1254 "upb/json/parser.rl" +#line 1293 "upb/json/parser.rl" { {stack[top++] = cs; cs = 19; goto _again;} } break; case 10: -#line 1256 "upb/json/parser.rl" +#line 1295 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 27; goto _again;} } break; case 11: -#line 1261 "upb/json/parser.rl" +#line 1300 "upb/json/parser.rl" { start_member(parser); } break; case 12: -#line 1262 "upb/json/parser.rl" +#line 1301 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 13: -#line 1265 "upb/json/parser.rl" +#line 1304 "upb/json/parser.rl" { end_member(parser); } break; case 14: -#line 1271 "upb/json/parser.rl" +#line 1310 "upb/json/parser.rl" { start_object(parser); } break; case 15: -#line 1274 "upb/json/parser.rl" +#line 1313 "upb/json/parser.rl" { end_object(parser); } break; case 16: -#line 1280 "upb/json/parser.rl" +#line 1319 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 17: -#line 1284 "upb/json/parser.rl" +#line 1323 "upb/json/parser.rl" { end_array(parser); } break; case 18: -#line 1289 "upb/json/parser.rl" +#line 1328 "upb/json/parser.rl" { start_number(parser, p); } break; case 19: -#line 1290 "upb/json/parser.rl" +#line 1329 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 20: -#line 1292 "upb/json/parser.rl" +#line 1331 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 21: -#line 1293 "upb/json/parser.rl" +#line 1332 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 22: -#line 1295 "upb/json/parser.rl" +#line 1334 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, true)); } break; case 23: -#line 1297 "upb/json/parser.rl" +#line 1336 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, false)); } break; case 24: -#line 1299 "upb/json/parser.rl" +#line 1338 "upb/json/parser.rl" { /* null value */ } break; case 25: -#line 1301 "upb/json/parser.rl" +#line 1340 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject(parser)); } break; case 26: -#line 1302 "upb/json/parser.rl" +#line 1341 "upb/json/parser.rl" { end_subobject(parser); } break; case 27: -#line 1307 "upb/json/parser.rl" +#line 1346 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 1579 "upb/json/parser.c" +#line 1618 "upb/json/parser.c" } } @@ -15836,7 +15875,7 @@ _again: _out: {} } -#line 1334 "upb/json/parser.rl" +#line 1373 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -15877,13 +15916,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 1633 "upb/json/parser.c" +#line 1672 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 1374 "upb/json/parser.rl" +#line 1413 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -15970,7 +16009,8 @@ static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { upb_json_parser *upb_json_parser_create(upb_env *env, const upb_json_parsermethod *method, - upb_sink *output) { + upb_sink *output, + bool ignore_json_unknown) { #ifndef NDEBUG const size_t size_before = upb_env_bytesallocated(env); #endif @@ -15989,6 +16029,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, p->top->m = upb_handlers_msgdef(output->handlers); set_name_table(p, p->top); + p->ignore_json_unknown = ignore_json_unknown; + /* If this fails, uncomment and increase the value in parser.h. */ /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= diff --git a/php/ext/google/protobuf/upb.h b/php/ext/google/protobuf/upb.h index a263db30..180f4715 100644 --- a/php/ext/google/protobuf/upb.h +++ b/php/ext/google/protobuf/upb.h @@ -9457,7 +9457,7 @@ UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted, class upb::json::Parser { public: static Parser* Create(Environment* env, const ParserMethod* method, - Sink* output); + Sink* output, bool ignore_json_unknown); BytesSink* input(); @@ -9491,7 +9491,8 @@ UPB_BEGIN_EXTERN_C upb_json_parser* upb_json_parser_create(upb_env* e, const upb_json_parsermethod* m, - upb_sink* output); + upb_sink* output, + bool ignore_json_unknown); upb_bytessink *upb_json_parser_input(upb_json_parser *p); upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md, @@ -9511,8 +9512,8 @@ UPB_END_EXTERN_C namespace upb { namespace json { inline Parser* Parser::Create(Environment* env, const ParserMethod* method, - Sink* output) { - return upb_json_parser_create(env, method, output); + Sink* output, bool ignore_json_unknown) { + return upb_json_parser_create(env, method, output, ignore_json_unknown); } inline BytesSink* Parser::input() { return upb_json_parser_input(this); -- cgit v1.2.3