From 0c6d1549602e32d05efc55cfd650589636f900d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 16 May 2026 13:03:07 +0000 Subject: [PATCH 1/3] Initial plan From ca80853ab9b34659edb36086fb9cb4f1bdb73d9f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 16 May 2026 13:26:29 +0000 Subject: [PATCH 2/3] Allow empty string identifiers on non-flags enums in JsonStringEnumConverter Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/b77c051c-b5f7-4943-9c20-6e4fe34c3b37 Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com> --- .../src/Resources/Strings.resx | 2 +- .../Converters/Value/EnumConverter.cs | 10 ++++---- .../Serialization/EnumConverterTests.cs | 24 +++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) 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)] From 36a53ea737f9dc007a61a95839d6630383f5c9be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 13:35:43 +0000 Subject: [PATCH 3/3] Add flags-enum test coverage for empty-string member name rejection Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/e6c2eed7-d610-4d2a-ba79-80c4760a113d Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com> --- .../Serialization/EnumConverterTests.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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 cb5c58460eb033..663ef75ba83482 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 @@ -1314,6 +1314,33 @@ public enum YesOrNoOrEmpty Empty, } + [Fact] + public static void EnumWithEmptyStringMemberName_Flags_Throws() + { + string expectedExceptionMessage = $"Enum type '{nameof(YesOrNoOrEmptyFlags)}' uses unsupported identifier ''."; + + InvalidOperationException ex = Assert.Throws( + () => JsonSerializer.Serialize(YesOrNoOrEmptyFlags.Yes, s_optionsWithStringEnumConverter)); + Assert.Contains(expectedExceptionMessage, ex.Message); + + ex = Assert.Throws( + () => JsonSerializer.Deserialize("\"y\"", s_optionsWithStringEnumConverter)); + Assert.Contains(expectedExceptionMessage, ex.Message); + } + + [Flags] + public enum YesOrNoOrEmptyFlags + { + [JsonStringEnumMemberName("y")] + Yes = 1, + + [JsonStringEnumMemberName("n")] + No = 2, + + [JsonStringEnumMemberName("")] + Empty = 4, + } + [Theory] [InlineData("\"cAmElCaSe\"", EnumWithVaryingNamingPolicies.camelCase, JsonKnownNamingPolicy.SnakeCaseUpper)] [InlineData("\"cAmElCaSe\"", EnumWithVaryingNamingPolicies.camelCase, JsonKnownNamingPolicy.SnakeCaseLower)]