diff --git a/src/Spoleto.Common.Tests/JsonHelperTests.cs b/src/Spoleto.Common.Tests/JsonHelperTests.cs index 4c41339..965e10b 100644 --- a/src/Spoleto.Common.Tests/JsonHelperTests.cs +++ b/src/Spoleto.Common.Tests/JsonHelperTests.cs @@ -30,7 +30,7 @@ public void EnumWithJsonEnumValueAttribute() // Arrange var obj = new TestClass { - Test = TestEnumValue.Two + Test1 = TestEnumValue.Two }; // Act @@ -40,7 +40,7 @@ public void EnumWithJsonEnumValueAttribute() // Assert Assert.Multiple(() => { - Assert.That(fromJson.Test, Is.EqualTo(obj.Test)); + Assert.That(fromJson.Test1, Is.EqualTo(obj.Test1)); Assert.That(json.Contains("T2"), Is.True); }); } @@ -51,7 +51,8 @@ public void EnumWithNullJsonEnumValueAttribute() // Arrange var obj = new TestClass { - Test = TestEnumValue.Null + Test1 = TestEnumValue.Null, + Test2 = TestEnumValue.Two }; // Act @@ -61,8 +62,11 @@ public void EnumWithNullJsonEnumValueAttribute() // Assert Assert.Multiple(() => { - Assert.That(fromJson.Test, Is.EqualTo(obj.Test)); - Assert.That(json.Contains("null"), Is.True); + Assert.That(fromJson.Test1, Is.EqualTo(obj.Test1)); + Assert.That(fromJson.Test2, Is.EqualTo(obj.Test2)); + + Assert.That(json, Does.Contain("null")); + Assert.That(json, Does.Contain("\"T2\"")); }); } diff --git a/src/Spoleto.Common.Tests/Objects/TestClass.cs b/src/Spoleto.Common.Tests/Objects/TestClass.cs index 8153e9e..42ce8b8 100644 --- a/src/Spoleto.Common.Tests/Objects/TestClass.cs +++ b/src/Spoleto.Common.Tests/Objects/TestClass.cs @@ -6,7 +6,10 @@ namespace Spoleto.Common.Tests public class TestClass { [JsonConverter(typeof(JsonEnumValueConverter))] - public TestEnumValue Test { get; set; } + public TestEnumValue Test1 { get; set; } + + [JsonConverter(typeof(JsonEnumValueConverter))] + public TestEnumValue Test2 { get; set; } [JsonConverter(typeof(JsonIntEnumConverter))] public TestIntEnum TestIntEnum { get; set; } diff --git a/src/Spoleto.Common.Tests/Objects/TestEnumValue.cs b/src/Spoleto.Common.Tests/Objects/TestEnumValue.cs index 80b5d05..b65428e 100644 --- a/src/Spoleto.Common.Tests/Objects/TestEnumValue.cs +++ b/src/Spoleto.Common.Tests/Objects/TestEnumValue.cs @@ -8,12 +8,12 @@ namespace Spoleto.Common.Tests public enum TestEnumValue { [JsonEnumValue("O1")] - One, + One = 1, [JsonEnumValue("T2")] - Two, + Two = 2, [JsonEnumValue(null)] - Null + Null = -1 } } diff --git a/src/Spoleto.Common/JsonConverters/JsonEnumIntValueConverter.cs b/src/Spoleto.Common/JsonConverters/JsonEnumIntValueConverter.cs index 71ba6a4..c1e218c 100644 --- a/src/Spoleto.Common/JsonConverters/JsonEnumIntValueConverter.cs +++ b/src/Spoleto.Common/JsonConverters/JsonEnumIntValueConverter.cs @@ -40,26 +40,44 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial } } - throw new JsonException($"Unknown enum element: {value}"); + if (value == 0) + { + return default; + } + + throw new JsonException($"Unknown enum '{typeof(T).Name}' element: {value}"); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { - var enumValue = GetEnumValue(value); - - if (enumValue == null) - writer.WriteNullValue(); + if (TryGetEnumValue(value, out var enumValue)) + { + if (enumValue == null) + writer.WriteNullValue(); + else + writer.WriteNumberValue(enumValue.Value); + } else - writer.WriteNumberValue(enumValue.Value); + { + writer.WriteNumberValue((int)(object)value); + } } - private int? GetEnumValue(Enum value) + private bool TryGetEnumValue(Enum value, out int? outValue) { var field = value.GetType().GetField(value.ToString()); - return field.GetCustomAttribute() is JsonEnumIntValueAttribute attribute + if (field == null) + { + outValue = null; + return false; + } + + outValue = field.GetCustomAttribute() is JsonEnumIntValueAttribute attribute ? attribute.Value : Convert.ToInt32(value); + + return true; } } } diff --git a/src/Spoleto.Common/JsonConverters/JsonEnumValueConverter.cs b/src/Spoleto.Common/JsonConverters/JsonEnumValueConverter.cs index d70cdb3..a69bd0b 100644 --- a/src/Spoleto.Common/JsonConverters/JsonEnumValueConverter.cs +++ b/src/Spoleto.Common/JsonConverters/JsonEnumValueConverter.cs @@ -19,6 +19,14 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial { value = null; } + else if (reader.TokenType == JsonTokenType.Number) + { + var numValue = reader.GetInt32(); + if (numValue == 0) + return default; + + throw new JsonException($"Unknown enum '{typeof(T).Name}' element: {numValue}"); + } else { value = reader.GetString(); @@ -40,26 +48,39 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial } } - throw new JsonException($"Unknown enum element: {value}"); + throw new JsonException($"Unknown enum '{typeof(T).Name}' element: {value}"); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { - var enumValue = GetEnumValue(value); - - if (enumValue == null) - writer.WriteNullValue(); + if (TryGetEnumValue(value, out var enumValue)) + { + if (enumValue == null) + writer.WriteNullValue(); + else + writer.WriteStringValue(enumValue); + } else - writer.WriteStringValue(enumValue); + { + writer.WriteNumberValue((int)(object)value); + } } - private string GetEnumValue(Enum value) + private bool TryGetEnumValue(Enum value, out string outValue) { var field = value.GetType().GetField(value.ToString()); - return field.GetCustomAttribute() is JsonEnumValueAttribute attribute + if (field == null) + { + outValue = null; + return false; + } + + outValue = field.GetCustomAttribute() is JsonEnumValueAttribute attribute ? attribute.Value : value.ToString(); + + return true; } } }