Add the ability to serialize enums values (#1898)

* Add the ablility to serialize enums values

* unit test
This commit is contained in:
Cheick Keita
2022-05-04 14:20:23 -07:00
committed by GitHub
parent b2399c4571
commit c07a908cf4
5 changed files with 325 additions and 290 deletions

View File

@ -1,6 +1,9 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
namespace Microsoft.OneFuzz.Service; namespace Microsoft.OneFuzz.Service;
[SerializeValue]
public enum ErrorCode { public enum ErrorCode {
INVALID_REQUEST = 450, INVALID_REQUEST = 450,
INVALID_PERMISSION = 451, INVALID_PERMISSION = 451,

View File

@ -268,7 +268,7 @@ namespace ApiService.TestHooks {
var s = await req.ReadAsStringAsync(); var s = await req.ReadAsStringAsync();
var markTasks = JsonSerializer.Deserialize<MarkTasks>(s!, EntityConverter.GetJsonSerializerOptions()); var markTasks = JsonSerializer.Deserialize<MarkTasks>(s!, EntityConverter.GetJsonSerializerOptions());
await _nodeOps.MarkTasksStoppedEarly(markTasks.node, markTasks.error); await _nodeOps.MarkTasksStoppedEarly(markTasks!.node, markTasks.error);
var resp = req.CreateResponse(HttpStatusCode.OK); var resp = req.CreateResponse(HttpStatusCode.OK);
return resp; return resp;

View File

@ -8,7 +8,7 @@ using System.Text.Json.Serialization;
namespace Microsoft.OneFuzz.Service.OneFuzzLib.Orm; namespace Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
public sealed class CustomEnumConverterFactory : JsonConverterFactory { public sealed class CustomEnumConverterFactory : JsonConverterFactory {
public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum; public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum && (typeToConvert.GetCustomAttribute<SerializeValueAttribute>() == null);
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) {
object[]? knownValues = null; object[]? knownValues = null;

View File

@ -19,6 +19,11 @@ public abstract record EntityBase {
public abstract record StatefulEntityBase<T>([property: JsonIgnore] T State) : EntityBase() where T : Enum; public abstract record StatefulEntityBase<T>([property: JsonIgnore] T State) : EntityBase() where T : Enum;
/// Indicates that the enum cases should no be renamed
[AttributeUsage(AttributeTargets.Enum)]
public class SerializeValueAttribute : Attribute { }
/// Indicates that the enum cases should no be renamed /// Indicates that the enum cases should no be renamed
[AttributeUsage(AttributeTargets.Enum)] [AttributeUsage(AttributeTargets.Enum)]
public class SkipRename : Attribute { } public class SkipRename : Attribute { }

View File

@ -14,6 +14,7 @@ namespace Tests {
public String? TheName { get; set; } public String? TheName { get; set; }
public TestEnum TheEnum { get; set; } public TestEnum TheEnum { get; set; }
public TestFlagEnum TheFlag { get; set; } public TestFlagEnum TheFlag { get; set; }
public TestEnumValue TheEnumValue { get; set; }
} }
enum TestEnum { enum TestEnum {
@ -27,6 +28,12 @@ namespace Tests {
FlagTwo = 2, FlagTwo = 2,
} }
[SerializeValue]
enum TestEnumValue {
One = 1,
Two = 2
}
record Entity1( record Entity1(
[PartitionKey] Guid Id, [PartitionKey] Guid Id,
[RowKey] string TheName, [RowKey] string TheName,
@ -60,7 +67,8 @@ namespace Tests {
new TestObject { new TestObject {
TheName = "testobject", TheName = "testobject",
TheEnum = TestEnum.TheTwo, TheEnum = TestEnum.TheTwo,
TheFlag = TestFlagEnum.FlagOne | TestFlagEnum.FlagTwo TheFlag = TestFlagEnum.FlagOne | TestFlagEnum.FlagTwo,
TheEnumValue = TestEnumValue.Two
}, },
null, null,
new Uri(uriString), new Uri(uriString),
@ -90,6 +98,7 @@ namespace Tests {
Assert.Equal(fromTableEntity.TheObject.TheEnum, entity1.TheObject.TheEnum); Assert.Equal(fromTableEntity.TheObject.TheEnum, entity1.TheObject.TheEnum);
Assert.Equal(fromTableEntity.TheObject.TheFlag, entity1.TheObject.TheFlag); Assert.Equal(fromTableEntity.TheObject.TheFlag, entity1.TheObject.TheFlag);
Assert.Equal(fromTableEntity.TheObject.TheName, entity1.TheObject.TheName); Assert.Equal(fromTableEntity.TheObject.TheName, entity1.TheObject.TheName);
Assert.Equal(fromTableEntity.TheObject.TheEnumValue, entity1.TheObject.TheEnumValue);
} }
@ -108,7 +117,8 @@ namespace Tests {
new TestObject { new TestObject {
TheName = "testobject", TheName = "testobject",
TheEnum = TestEnum.TheTwo, TheEnum = TestEnum.TheTwo,
TheFlag = TestFlagEnum.FlagOne | TestFlagEnum.FlagTwo TheFlag = TestFlagEnum.FlagOne | TestFlagEnum.FlagTwo,
TheEnumValue = TestEnumValue.One
}, },
null, null,
new Uri(uriString), new Uri(uriString),
@ -134,11 +144,12 @@ namespace Tests {
json.TryGetPropertyValue("the_name", out var theName); json.TryGetPropertyValue("the_name", out var theName);
json.TryGetPropertyValue("the_enum", out var theEnum); json.TryGetPropertyValue("the_enum", out var theEnum);
json.TryGetPropertyValue("the_flag", out var theFlag); json.TryGetPropertyValue("the_flag", out var theFlag);
json.TryGetPropertyValue("the_enum_value", out var theEnumValue);
Assert.Equal(entity1.TheObject.TheName, theName?.GetValue<string>()); Assert.Equal(entity1.TheObject.TheName, theName?.GetValue<string>());
Assert.Equal("the_two", theEnum?.GetValue<string>()); Assert.Equal("the_two", theEnum?.GetValue<string>());
Assert.Equal("flag_one,flag_two", theFlag?.GetValue<string>()); Assert.Equal("flag_one,flag_two", theFlag?.GetValue<string>());
Assert.Equal((int)TestEnumValue.One, theEnumValue?.GetValue<int>());
} }
[Fact] [Fact]
@ -303,5 +314,21 @@ namespace Tests {
Assert.Equal(expected.Container.ContainerName, tableEntity.GetString("container")); Assert.Equal(expected.Container.ContainerName, tableEntity.GetString("container"));
} }
record TestEnumObject(TestEnumValue TheEnumValue);
[Fact]
public void TestSerializeEnumValue() {
var expectedObject = new TestEnumObject(
TheEnumValue: TestEnumValue.One
);
var serialized = JsonSerializer.Serialize(expectedObject, EntityConverter.GetJsonSerializerOptions());
var json = JsonDocument.Parse(serialized);
Assert.Equal((int)expectedObject.TheEnumValue, json.RootElement.GetProperty("the_enum_value").GetInt32());
var actual = JsonSerializer.Deserialize<TestEnumObject>(serialized, EntityConverter.GetJsonSerializerOptions());
Assert.Equal(expectedObject, actual);
}
} }
} }