From 825952b7fa5ac1c6e9bd4eb610e0539aaf0ce370 Mon Sep 17 00:00:00 2001 From: Alexey Volkov Date: Wed, 7 Feb 2024 01:37:10 -0800 Subject: [PATCH] feat: Made enum name parsing case-insensitive in Python The enum names are expected to be case-insensitive. Fixes https://github.com/protocolbuffers/protobuf/issues/15757 PiperOrigin-RevId: 604904921 --- conformance/binary_json_conformance_suite.cc | 3 +++ conformance/failure_list_cpp.txt | 8 ++++++++ conformance/failure_list_java.txt | 2 ++ python/google/protobuf/json_format.py | 11 +++++++++++ 4 files changed, 24 insertions(+) diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc index ede4710cc65e..85a16c47e10f 100644 --- a/conformance/binary_json_conformance_suite.cc +++ b/conformance/binary_json_conformance_suite.cc @@ -2497,6 +2497,9 @@ void BinaryAndJsonConformanceSuiteImpl< // Enum fields. RunValidJsonTest("EnumField", REQUIRED, R"({"optionalNestedEnum": "FOO"})", "optional_nested_enum: FOO"); + RunValidJsonTest("EnumFieldDifferentCase", RECOMMENDED, + R"({"optionalNestedEnum": "fOo"})", + "optional_nested_enum: FOO"); // Enum fields with alias if (run_proto3_tests_) { diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt index 7c52e23d96c8..c1d74b096178 100644 --- a/conformance/failure_list_cpp.txt +++ b/conformance/failure_list_cpp.txt @@ -35,3 +35,11 @@ Recommended.*.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.*.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't. Recommended.*.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't. Recommended.*.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't. +Recommended.Editions_Proto2.JsonInput.EnumFieldDifferentCase.JsonOutput +Recommended.Editions_Proto2.JsonInput.EnumFieldDifferentCase.ProtobufOutput +Recommended.Editions_Proto3.JsonInput.EnumFieldDifferentCase.JsonOutput +Recommended.Editions_Proto3.JsonInput.EnumFieldDifferentCase.ProtobufOutput +Recommended.Proto2.JsonInput.EnumFieldDifferentCase.JsonOutput +Recommended.Proto2.JsonInput.EnumFieldDifferentCase.ProtobufOutput +Recommended.Proto3.JsonInput.EnumFieldDifferentCase.JsonOutput +Recommended.Proto3.JsonInput.EnumFieldDifferentCase.ProtobufOutput diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt index 9e2e525568c0..6345df5c44ef 100644 --- a/conformance/failure_list_java.txt +++ b/conformance/failure_list_java.txt @@ -35,6 +35,8 @@ Recommended.*.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.*.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't. Recommended.*.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't. Recommended.*.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't. +Recommended.*.JsonInput.EnumFieldDifferentCase.JsonOutput +Recommended.*.JsonInput.EnumFieldDifferentCase.ProtobufOutput Required.*.JsonInput.EnumFieldNotQuoted # Should have failed to parse, but didn't. Required.*.JsonInput.Int32FieldLeadingZero # Should have failed to parse, but didn't. Required.*.JsonInput.Int32FieldNegativeWithLeadingZero # Should have failed to parse, but didn't. diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py index 2a6bba9391bd..c8eef81792a3 100644 --- a/python/google/protobuf/json_format.py +++ b/python/google/protobuf/json_format.py @@ -920,6 +920,17 @@ def _ConvertScalarFieldValue(value, field, path, require_str=False): elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: # Convert an enum value. enum_value = field.enum_type.values_by_name.get(value, None) + if enum_value is None and isinstance(value, str): + # Performing case insensitive search + enum_values = [ + enum_value + for enum_name, enum_value in field.enum_type.values_by_name.items() + if enum_name.upper() == value.upper() + ] + # Note: There can be multiple items where the name only differs in case. + # Let's take the 1st one. + if enum_values: + enum_value = enum_values[0] if enum_value is None: try: number = int(value)