diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index b67fc02b7a5a86..8b259b4fa14212 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -232,7 +232,7 @@ '{0}' is invalid within a JSON string. The string should be correctly escaped. - Enum type '{0}' uses unsupported identifier '{1}'. It must not be null, empty, or containing leading or trailing whitespace. Flags enums must additionally not contain commas. + Enum type '{0}' uses unsupported identifier '{1}'. It must not be null nor contain leading or trailing whitespace. Flags enums must additionally not be empty nor contain commas. '{0}' is an invalid token type for the end of the JSON payload. Expected either 'EndArray' or 'EndObject'. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs index ebc89780decd41..49b7fe4802ed51 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs @@ -572,11 +572,13 @@ private static string ResolveAndValidateJsonName(string name, JsonNamingPolicy? name = namingPolicy.ConvertName(name); } - if (string.IsNullOrEmpty(name) || char.IsWhiteSpace(name[0]) || char.IsWhiteSpace(name[name.Length - 1]) || - (s_isFlagsEnum && name.Contains(','))) + if (name is null || + (name.Length > 0 && (char.IsWhiteSpace(name[0]) || char.IsWhiteSpace(name[name.Length - 1]))) || + (s_isFlagsEnum && (name.Length == 0 || name.Contains(',')))) { - // Reject null or empty strings or strings with leading or trailing whitespace. - // In the case of flags additionally reject strings containing commas. + // Reject null strings or strings with leading or trailing whitespace. + // In the case of flags additionally reject empty strings or strings containing commas, + // both of which would introduce ambiguity in flag value parsing and formatting. ThrowHelper.ThrowInvalidOperationException_UnsupportedEnumIdentifier(typeof(T), name); } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs index ada90fab227649..cb5c58460eb033 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs @@ -1259,6 +1259,7 @@ public enum EnumWithInvalidMemberName1 Value } + [Flags] public enum EnumWithInvalidMemberName2 { [JsonStringEnumMemberName("")] @@ -1290,6 +1291,29 @@ public enum EnumWithInvalidMemberName6 Value } + [Theory] + [InlineData(YesOrNoOrEmpty.Yes, "\"y\"")] + [InlineData(YesOrNoOrEmpty.No, "\"n\"")] + [InlineData(YesOrNoOrEmpty.Empty, "\"\"")] + public static void EnumWithEmptyStringMemberName_NonFlags_RoundtripsAsExpected(YesOrNoOrEmpty value, string expectedJson) + { + string json = JsonSerializer.Serialize(value, s_optionsWithStringEnumConverter); + Assert.Equal(expectedJson, json); + Assert.Equal(value, JsonSerializer.Deserialize(json, s_optionsWithStringEnumConverter)); + } + + public enum YesOrNoOrEmpty + { + [JsonStringEnumMemberName("y")] + Yes, + + [JsonStringEnumMemberName("n")] + No, + + [JsonStringEnumMemberName("")] + Empty, + } + [Theory] [InlineData("\"cAmElCaSe\"", EnumWithVaryingNamingPolicies.camelCase, JsonKnownNamingPolicy.SnakeCaseUpper)] [InlineData("\"cAmElCaSe\"", EnumWithVaryingNamingPolicies.camelCase, JsonKnownNamingPolicy.SnakeCaseLower)]