Skip to content

Commit

Permalink
Merge pull request #15 from criipto/tolerant-enums
Browse files Browse the repository at this point in the history
future-proof enum values with tolerant enum reading
  • Loading branch information
sgryt authored May 16, 2023
2 parents 62dd31e + 8ee543d commit 22a3b6a
Show file tree
Hide file tree
Showing 4 changed files with 449 additions and 10 deletions.
38 changes: 38 additions & 0 deletions Criipto.Signatures.UnitTests/ConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Xunit;
using Newtonsoft.Json;
using Criipto.Signatures.Models;

namespace Criipto.Signatures.UnitTests;

public class ConverterTests
{
[Fact]
public void SignatoryDocumentEdgeIsTolerant()
{
var json = """
{
"status": "SIGNED_IN_THE_FUTURE"
}
""".Trim();

var actual = JsonConvert.DeserializeObject<SignatoryDocumentEdge>(json);

Assert.NotNull(actual);
Assert.Equal(SignatoryDocumentStatus.FUTURE_ADDED_VALUE, actual!.status);
}

[Fact]
public void SignatoryDocumentEdgeIsCorrect()
{
var json = """
{
"status": "SIGNED"
}
""".Trim();

var actual = JsonConvert.DeserializeObject<SignatoryDocumentEdge>(json);

Assert.NotNull(actual);
Assert.Equal(SignatoryDocumentStatus.SIGNED, actual!.status);
}
}
67 changes: 67 additions & 0 deletions Criipto.Signatures/Converters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,71 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer
throw new NotImplementedException("Tried to write a GQL Composition type list to JSON");
}
}

public class TolerantEnumConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
if (objectType == null) return false;
Type? type = IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType;
if (type == null) return false;
return type.IsEnum;
}

public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
bool isNullable = IsNullableType(objectType);
Type? enumType = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType;

if (enumType == null) return null;

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

if (reader.TokenType == JsonToken.String)
{
string? enumText = reader.Value?.ToString();
Console.WriteLine(enumText);

if (!string.IsNullOrEmpty(enumText))
{
string? match = names
.Where(n => string.Equals(n, enumText, StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();

if (match != null)
{
return Enum.Parse(enumType, match);
}

string? defaultName = names
.Where(n => string.Equals(n, "FUTURE_ADDED_VALUE", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();

if (defaultName == null)
{
defaultName = names.First();
}

return Enum.Parse(enumType, defaultName);
}
}

return null;
}

public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteValue("null");
return;
}
writer.WriteValue(value.ToString());
}

private static bool IsNullableType(Type t)
{
return (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
}
}
}
Loading

0 comments on commit 22a3b6a

Please sign in to comment.