Skip to content

Commit 1743ec7

Browse files
committed
Add fallback
1 parent d780a66 commit 1743ec7

File tree

4 files changed

+45
-6
lines changed

4 files changed

+45
-6
lines changed

src/Grpc/JsonTranscoding/src/Microsoft.AspNetCore.Grpc.JsonTranscoding/GrpcJsonSettings.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,16 @@ public sealed class GrpcJsonSettings
5050
/// }
5151
/// </code>
5252
/// <para>
53-
/// <c>STATUS</c> prefix is removed from enum values when <see cref="RemoveEnumPrefix"/> is set to <see langword="true"/>.
54-
/// The enum values above will be read and written as <c>UNKNOWN</c> and <c>OK</c> instead of <c>STATUS_UNKNOWN</c>
55-
/// and <c>STATUS_OK</c>.
53+
/// When <see cref="RemoveEnumPrefix"/> is set to <see langword="true"/>:
5654
/// </para>
55+
/// <list type="bullet">
56+
/// <item>
57+
/// <description>The <c>STATUS</c> prefix is removed from enum values. The enum values above will be read and written as <c>UNKNOWN</c> and <c>OK</c> instead of <c>STATUS_UNKNOWN</c> and <c>STATUS_OK</c>.</description>
58+
/// </item>
59+
/// <item>
60+
/// <description>Original prefixed values are used as a fallback when reading JSON. For example, <c>STATUS_OK</c> and <c>OK</c> map to the <c>STATUS_OK</c> enum value.</description>
61+
/// </item>
62+
/// </list>
5763
/// <para>
5864
/// The Protobuf JSON specification requires enum values in JSON to match enum fields exactly.
5965
/// Enabling this option may reduce interoperability, as removing enum prefix might not be supported

src/Grpc/JsonTranscoding/src/Microsoft.AspNetCore.Grpc.JsonTranscoding/Internal/Json/EnumNameHelpers.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ private static EnumMapping GetEnumMapping(string enumName, Type enumType)
7575

7676
var writeMapping = nameMappings.ToDictionary(m => m.Value, m => m);
7777

78+
// Add original names as fallback when mapping enum values with removed prefixes.
79+
// There are added to the dictionary first so they are overridden by the mappings with removed prefixes.
80+
var removeEnumPrefixMapping = nameMappings.ToDictionary(m => m.OriginalName, m => m.OriginalName);
81+
7882
// Protobuf codegen prevents collision of enum names when the prefix is removed.
7983
// For example, the following enum will fail to build because both fields would resolve to "OK":
8084
//
@@ -89,9 +93,10 @@ private static EnumMapping GetEnumMapping(string enumName, Type enumType)
8993
// (If you are using allow_alias, please assign the same number to each enum value name.)
9094
//
9195
// Just in case it does happen, map to the first value rather than error.
92-
var removeEnumPrefixMapping = nameMappings
93-
.GroupBy(m => m.RemoveEnumPrefixName)
94-
.ToDictionary(g => g.Key, g => g.First().OriginalName, StringComparer.Ordinal);
96+
foreach (var item in nameMappings.GroupBy(m => m.RemoveEnumPrefixName).Select(g => KeyValuePair.Create(g.Key, g.First().OriginalName)))
97+
{
98+
removeEnumPrefixMapping[item.Key] = item.Value;
99+
}
95100

96101
return new EnumMapping { WriteMapping = writeMapping, RemoveEnumPrefixMapping = removeEnumPrefixMapping };
97102
}

src/Grpc/JsonTranscoding/test/Microsoft.AspNetCore.Grpc.JsonTranscoding.Tests/ConverterTests/JsonConverterReadTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,9 @@ public void Enum_ReadString(string value, HelloRequest.Types.DataTypes.Types.Nes
245245

246246
[Theory]
247247
[InlineData("UNSPECIFIED", PrefixEnumType.Types.PrefixEnum.Unspecified)]
248+
[InlineData("PREFIX_ENUM_UNSPECIFIED", PrefixEnumType.Types.PrefixEnum.Unspecified)]
248249
[InlineData("FOO", PrefixEnumType.Types.PrefixEnum.Foo)]
250+
[InlineData("PREFIX_ENUM_FOO", PrefixEnumType.Types.PrefixEnum.Foo)]
249251
[InlineData("BAR", PrefixEnumType.Types.PrefixEnum.Bar)]
250252
public void Enum_RemovePrefix_ReadString(string value, PrefixEnumType.Types.PrefixEnum expectedValue)
251253
{
@@ -258,6 +260,23 @@ public void Enum_RemovePrefix_ReadString(string value, PrefixEnumType.Types.Pref
258260
Assert.Equal(expectedValue, result.SingleEnum);
259261
}
260262

263+
[Theory]
264+
[InlineData("UNSPECIFIED", CollisionPrefixEnumType.Types.CollisionPrefixEnum.Unspecified)]
265+
[InlineData("COLLISION_PREFIX_ENUM_UNSPECIFIED", CollisionPrefixEnumType.Types.CollisionPrefixEnum.Unspecified)]
266+
[InlineData("FOO", CollisionPrefixEnumType.Types.CollisionPrefixEnum.Foo)]
267+
[InlineData("COLLISION_PREFIX_ENUM_FOO", CollisionPrefixEnumType.Types.CollisionPrefixEnum.CollisionPrefixEnumFoo)] // Match exact rather than fallback.
268+
[InlineData("COLLISION_PREFIX_ENUM_COLLISION_PREFIX_ENUM_FOO", CollisionPrefixEnumType.Types.CollisionPrefixEnum.CollisionPrefixEnumFoo)]
269+
public void Enum_RemovePrefix_Collision_ReadString(string value, CollisionPrefixEnumType.Types.CollisionPrefixEnum expectedValue)
270+
{
271+
var serviceDescriptorRegistry = new DescriptorRegistry();
272+
serviceDescriptorRegistry.RegisterFileDescriptor(JsonTranscodingGreeter.Descriptor.File);
273+
274+
var json = @$"{{ ""singleEnum"": ""{value}"" }}";
275+
276+
var result = AssertReadJson<CollisionPrefixEnumType>(json, descriptorRegistry: serviceDescriptorRegistry, serializeOld: false, settings: new GrpcJsonSettings { RemoveEnumPrefix = true });
277+
Assert.Equal(expectedValue, result.SingleEnum);
278+
}
279+
261280
[Fact]
262281
public void Enum_ReadString_NotAllowedValue()
263282
{

src/Grpc/JsonTranscoding/test/Microsoft.AspNetCore.Grpc.JsonTranscoding.Tests/Proto/transcoding.proto

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,12 @@ message PrefixEnumType {
246246
}
247247
PrefixEnum single_enum = 1;
248248
}
249+
250+
message CollisionPrefixEnumType {
251+
enum CollisionPrefixEnum {
252+
COLLISION_PREFIX_ENUM_UNSPECIFIED = 0;
253+
COLLISION_PREFIX_ENUM_FOO = 1;
254+
COLLISION_PREFIX_ENUM_COLLISION_PREFIX_ENUM_FOO = 2;
255+
}
256+
CollisionPrefixEnum single_enum = 1;
257+
}

0 commit comments

Comments
 (0)