Skip to content

Commit d8df420

Browse files
committed
Enum conversion was ignoring the EnumMember attribute
Fixed custom enum conversion to first try to use Json.NET's StringEnumConverter. If that fails, then fall back to identifying the appropriate fallback: null, Unknown, then the first enum value.
1 parent 845563e commit d8df420

2 files changed

Lines changed: 25 additions & 14 deletions

File tree

src/corelib/Serialization/TolerantEnumConverter.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
using System;
22
using System.Linq;
33
using Newtonsoft.Json;
4+
using Newtonsoft.Json.Converters;
45

56
namespace OpenStack.Serialization
67
{
78
/// <summary>
89
/// Attempts to convert a string to an enum using the following resolution strategy:
9-
/// <para>1. Use the name of the enum.</para>
10+
/// <para>1. Use StringEnumConverter.</para>
1011
/// <para>2. Use null if the property is nullable.</para>
1112
/// <para>3. Use the Unknown enum value.</para>
1213
/// <para>4. Use the first enum value.</para>
1314
/// </summary>
1415
/// <seealso href="http://stackoverflow.com/a/22755077/808818"/>
1516
/// <exclude />
16-
public class TolerantEnumConverter : JsonConverter
17+
public class TolerantEnumConverter : StringEnumConverter
1718
{
1819
/// <inheritdoc/>
1920
public override bool CanConvert(Type objectType)
@@ -25,20 +26,19 @@ public override bool CanConvert(Type objectType)
2526
/// <inheritdoc/>
2627
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
2728
{
29+
try
30+
{
31+
return base.ReadJson(reader, objectType, existingValue, serializer);
32+
}
33+
catch (JsonSerializationException)
34+
{
35+
36+
}
2837
bool isNullable = IsNullableType(objectType);
2938
Type enumType = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType;
3039

3140
string[] names = Enum.GetNames(enumType);
3241

33-
string enumText = reader.Value.ToString();
34-
35-
if (!string.IsNullOrEmpty(enumText))
36-
{
37-
string match = names.FirstOrDefault(n => string.Equals(n, enumText, StringComparison.OrdinalIgnoreCase));
38-
if (match != null)
39-
return Enum.Parse(enumType, match);
40-
}
41-
4242
if (!isNullable)
4343
{
4444
string defaultName = names.FirstOrDefault(n => string.Equals(n, "Unknown", StringComparison.OrdinalIgnoreCase));

src/testing/unit/Serialization/TolerantEnumConverterTests.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Newtonsoft.Json;
1+
using System.Runtime.Serialization;
2+
using Newtonsoft.Json;
23
using Xunit;
34

45
namespace OpenStack.Serialization
@@ -9,7 +10,9 @@ public class TolerantEnumConverterTests
910
enum ThingStatus
1011
{
1112
Active,
12-
Unknown
13+
Unknown,
14+
[EnumMember(Value = "REMOVE_FAILED")]
15+
RemoveFailed
1316
}
1417

1518
[JsonConverter(typeof(TolerantEnumConverter))]
@@ -22,11 +25,19 @@ enum StuffStatus
2225
[Fact]
2326
public void WhenValueIsRecognized_MatchToValue()
2427
{
25-
var result = JsonConvert.DeserializeObject<ThingStatus>("\"Active\"");
28+
var result = JsonConvert.DeserializeObject<ThingStatus>("\"ACTIVE\"");
2629

2730
Assert.Equal(ThingStatus.Active, result);
2831
}
2932

33+
[Fact]
34+
public void WhenAttributedValueIsRecognized_MatchToValue()
35+
{
36+
var result = JsonConvert.DeserializeObject<ThingStatus>("\"REMOVE_FAILED\"");
37+
38+
Assert.Equal(ThingStatus.RemoveFailed, result);
39+
}
40+
3041
[Fact]
3142
public void WhenValueIsUnrecognized_MatchToUnknownValue()
3243
{

0 commit comments

Comments
 (0)