Deserializer should handle nullable StringEnum<T> (#1760)

* add deserializer tests for nullable enums, StringEnum and nullable StringEnum properties

* Fix deserializing nullable structs by using the underlying type when nullable

* StringEnum<T> should behave like an enum, returning default(T) when it is uninitialised/null/blank

* Don't allow null to be passed into StringEnum ctor - if it needs to be null then it should be declared as nullable

* fix expected json

* move logic to determine if property is a StringEnum<T> into helper function

* serializer needs to treat StringEnum<T> specially by serializing the enum value according to existing serializer strategy (parameter attributes and so on)

* remove fallback to default(T)

* add test to assert ctor throws exception when null passed in

* remove test for default(T) fallback behaviour

* Fix exception in serializer test - StringEnum property must be initialized otherwise an exception is thrown when attempting to serialize

* Dont allow empty strings either
This commit is contained in:
Ryan Gribble
2018-02-16 20:12:44 +10:00
committed by GitHub
parent b35b60f24c
commit 41b4059c11
5 changed files with 151 additions and 41 deletions
+22 -17
View File
@@ -66,8 +66,21 @@ namespace Octokit.Internal
Ensure.ArgumentNotNull(input, "input");
var type = input.GetType();
var jsonObject = new JsonObject();
var getters = GetCache[type];
if (ReflectionUtils.IsStringEnumWrapper(type))
{
// Handle StringEnum<T> by getting the underlying enum value, then using the enum serializer
// Note this will throw if the StringEnum<T> was initialised using a string that is not a valid enum member
var inputEnum = (getters["value"](input) as Enum);
if (inputEnum != null)
{
output = SerializeEnum(inputEnum);
return true;
}
}
var jsonObject = new JsonObject();
foreach (var getter in getters)
{
if (getter.Value != null)
@@ -134,6 +147,12 @@ namespace Octokit.Internal
if (stringValue != null)
{
// If it's a nullable type, use the underlying type
if (ReflectionUtils.IsNullableType(type))
{
type = Nullable.GetUnderlyingType(type);
}
var typeInfo = ReflectionUtils.GetTypeInfo(type);
if (typeInfo.IsEnum)
@@ -141,15 +160,6 @@ namespace Octokit.Internal
return DeserializeEnumHelper(stringValue, type);
}
if (ReflectionUtils.IsNullableType(type))
{
var underlyingType = Nullable.GetUnderlyingType(type);
if (ReflectionUtils.GetTypeInfo(underlyingType).IsEnum)
{
return DeserializeEnumHelper(stringValue, underlyingType);
}
}
if (ReflectionUtils.IsTypeGenericeCollectionInterface(type))
{
// OAuth tokens might be a string of comma-separated values
@@ -161,14 +171,9 @@ namespace Octokit.Internal
}
}
if (typeInfo.IsGenericType)
if (ReflectionUtils.IsStringEnumWrapper(type))
{
var typeDefinition = typeInfo.GetGenericTypeDefinition();
if (typeof(StringEnum<>).IsAssignableFrom(typeDefinition))
{
return Activator.CreateInstance(type, stringValue);
}
return Activator.CreateInstance(type, stringValue);
}
}
else if (jsonValue != null)