-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add JsonStringEnumMemberConverter
- Loading branch information
1 parent
d00d39b
commit a7c5945
Showing
10 changed files
with
211 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
src/Atc/Serialization/JsonConverters/JsonStringEnumMemberConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
namespace Atc.Serialization.JsonConverters; | ||
|
||
public sealed class JsonStringEnumMemberConverter<T> : JsonConverter<T> | ||
where T : Enum | ||
{ | ||
public override T Read( | ||
ref Utf8JsonReader reader, | ||
Type typeToConvert, | ||
JsonSerializerOptions options) | ||
{ | ||
if (typeToConvert is null) | ||
{ | ||
throw new ArgumentNullException(nameof(typeToConvert)); | ||
} | ||
|
||
var enumValue = reader.GetString(); | ||
foreach (var field in typeToConvert.GetFields()) | ||
{ | ||
var enumMemberAttribute = field.GetCustomAttribute<EnumMemberAttribute>(); | ||
|
||
switch (enumMemberAttribute) | ||
{ | ||
case null when | ||
field.Name.Equals(enumValue, StringComparison.OrdinalIgnoreCase): | ||
return (T)field.GetValue(null); | ||
case null: | ||
continue; | ||
} | ||
|
||
if (enumMemberAttribute.Value.Equals(enumValue, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return (T)field.GetValue(null); | ||
} | ||
} | ||
|
||
throw new JsonException($"Unable to convert \"{enumValue}\" to Enum \"{typeToConvert}\"."); | ||
} | ||
|
||
public override void Write( | ||
Utf8JsonWriter writer, | ||
T value, | ||
JsonSerializerOptions options) | ||
{ | ||
if (writer is null) | ||
{ | ||
throw new ArgumentNullException(nameof(writer)); | ||
} | ||
|
||
if (options is null) | ||
{ | ||
throw new ArgumentNullException(nameof(options)); | ||
} | ||
|
||
var enumMemberAttribute = value | ||
.GetType() | ||
.GetField(value.ToString()) | ||
.GetCustomAttribute<EnumMemberAttribute>(); | ||
|
||
var enumValue = enumMemberAttribute?.Value ?? value.ToString(); | ||
|
||
writer.WriteStringValue(options.PropertyNamingPolicy == JsonNamingPolicy.CamelCase | ||
? enumValue.EnsureFirstCharacterToLower() | ||
: enumValue.EnsureFirstCharacterToUpper()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
test/Atc.Tests/Serialization/JsonConverters/JsonStringEnumMemberConverterTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
namespace Atc.Tests.Serialization.JsonConverters; | ||
|
||
public class JsonStringEnumMemberConverterTests | ||
{ | ||
[Theory] | ||
[InlineData(ChargePointState.BusyNonCharging, "busy-non-charging")] | ||
[InlineData(ChargePointState.TestWithoutEnumMember, "testWithoutEnumMember")] | ||
public void Read_ShouldReturnExpectedChargePointState(ChargePointState expected, string enumValue) | ||
{ | ||
// Arrange | ||
var jsonSerializerOptions = JsonSerializerOptionsFactory.Create(); | ||
var jsonConverter = new JsonStringEnumMemberConverter<ChargePointState>(); | ||
var json = $"\"{enumValue.Replace("\\", "\\\\", StringComparison.Ordinal)}\""; | ||
var utf8JsonReader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); | ||
|
||
utf8JsonReader.Read(); | ||
|
||
// Act | ||
var result = jsonConverter.Read(ref utf8JsonReader, typeof(ChargePointState), jsonSerializerOptions); | ||
|
||
// Assert | ||
if (OperatingSystem.IsWindows()) | ||
{ | ||
Assert.Equal(expected, result); | ||
} | ||
} | ||
|
||
[Theory] | ||
[InlineData("busy-non-charging", ChargePointState.BusyNonCharging)] | ||
[InlineData("testWithoutEnumMember", ChargePointState.TestWithoutEnumMember)] | ||
public void Write_ShouldWriteChargePointStateToUtf8JsonWriter(string expected, ChargePointState chargePointState) | ||
{ | ||
// Arrange | ||
var jsonSerializerOptions = JsonSerializerOptionsFactory.Create(); | ||
var jsonConverter = new JsonStringEnumMemberConverter<ChargePointState>(); | ||
var memoryStream = new MemoryStream(); | ||
using var utf8JsonWriter = new Utf8JsonWriter(memoryStream); | ||
|
||
// Act | ||
jsonConverter.Write(utf8JsonWriter, chargePointState, jsonSerializerOptions); | ||
|
||
// Assert | ||
utf8JsonWriter.Flush(); | ||
var result = Encoding.UTF8.GetString(memoryStream.ToArray()); | ||
|
||
if (OperatingSystem.IsWindows()) | ||
{ | ||
Assert.Equal($"\"{expected}\"", result.Replace("\\\\", "\\", StringComparison.Ordinal)); | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
test/Atc.Tests/Serialization/XUnitTestTypes/ChargePointState.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
namespace Atc.Tests.Serialization.XUnitTestTypes; | ||
|
||
[SuppressMessage("Naming", "CA1700:Do not name enum values 'Reserved'", Justification = "OK - For testing.")] | ||
[JsonConverter(typeof(JsonStringEnumConverter))] | ||
public enum ChargePointState | ||
{ | ||
[EnumMember(Value = "available")] | ||
Available, | ||
|
||
[EnumMember(Value = "busy")] | ||
Busy, | ||
|
||
[EnumMember(Value = "busy-blocked")] | ||
BusyBlocked, | ||
|
||
[EnumMember(Value = "busy-charging")] | ||
BusyCharging, | ||
|
||
[EnumMember(Value = "busy-non-charging")] | ||
BusyNonCharging, | ||
|
||
[EnumMember(Value = "busy-non-released")] | ||
BusyNonReleased, | ||
|
||
[EnumMember(Value = "busy-reserved")] | ||
BusyReserved, | ||
|
||
[EnumMember(Value = "busy-scheduled")] | ||
BusyScheduled, | ||
|
||
[EnumMember(Value = "error")] | ||
Error, | ||
|
||
[EnumMember(Value = "disconnected")] | ||
Disconnected, | ||
|
||
[EnumMember(Value = "passive")] | ||
Passive, | ||
|
||
[EnumMember(Value = "maintenance")] | ||
Maintenance, | ||
|
||
[EnumMember(Value = "other")] | ||
Other, | ||
|
||
TestWithoutEnumMember, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters