Skip to content

Commit 65a0e71

Browse files
committed
Fix nullable enum roundtrip
1 parent 27c7bc3 commit 65a0e71

File tree

2 files changed

+75
-63
lines changed

2 files changed

+75
-63
lines changed

YamlDotNet.Test/Serialization/SerializationTests.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,25 @@ public void DeserializeScalarLongBase60Number()
162162
result.Should().Be(77744246530L);
163163
}
164164

165-
[Fact]
166-
public void RoundtripEnums()
165+
[Theory]
166+
[InlineData(EnumExample.One)]
167+
[InlineData(EnumExample.One | EnumExample.Two)]
168+
public void RoundtripEnums(EnumExample value)
167169
{
168-
var flags = EnumExample.One | EnumExample.Two;
170+
var result = DoRoundtripFromObjectTo<EnumExample>(value);
171+
172+
result.Should().Be(value);
173+
}
169174

170-
var result = DoRoundtripFromObjectTo<EnumExample>(flags);
175+
[Theory]
176+
[InlineData(EnumExample.One)]
177+
[InlineData(EnumExample.One | EnumExample.Two)]
178+
[InlineData(null)]
179+
public void RoundtripNullableEnums(EnumExample? value)
180+
{
181+
var result = DoRoundtripFromObjectTo<EnumExample?>(value);
171182

172-
result.Should().Be(flags);
183+
result.Should().Be(value);
173184
}
174185

175186
[Fact]

YamlDotNet/Serialization/NodeDeserializers/ScalarNodeDeserializer.cs

Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -42,68 +42,69 @@ bool INodeDeserializer.Deserialize(IParser parser, Type expectedType, Func<IPars
4242
return false;
4343
}
4444

45-
if (expectedType.IsEnum())
45+
// Strip off the nullable type, if present
46+
var underlyingType = Nullable.GetUnderlyingType(expectedType) ?? expectedType;
47+
48+
if (underlyingType.IsEnum())
4649
{
47-
value = Enum.Parse(expectedType, scalar.Value, true);
50+
value = Enum.Parse(underlyingType, scalar.Value, true);
51+
return true;
4852
}
49-
else
50-
{
51-
var underlyingType = Nullable.GetUnderlyingType(expectedType);
52-
var typeCode = underlyingType != null ? underlyingType.GetTypeCode() : expectedType.GetTypeCode();
53-
switch (typeCode)
54-
{
55-
case TypeCode.Boolean:
56-
value = DeserializeBooleanHelper(scalar.Value);
57-
break;
5853

59-
case TypeCode.Byte:
60-
case TypeCode.Int16:
61-
case TypeCode.Int32:
62-
case TypeCode.Int64:
63-
case TypeCode.SByte:
64-
case TypeCode.UInt16:
65-
case TypeCode.UInt32:
66-
case TypeCode.UInt64:
67-
value = DeserializeIntegerHelper(typeCode, scalar.Value);
68-
break;
69-
70-
case TypeCode.Single:
71-
value = Single.Parse(scalar.Value, YamlFormatter.NumberFormat);
72-
break;
73-
74-
case TypeCode.Double:
75-
value = Double.Parse(scalar.Value, YamlFormatter.NumberFormat);
76-
break;
77-
78-
case TypeCode.Decimal:
79-
value = Decimal.Parse(scalar.Value, YamlFormatter.NumberFormat);
80-
break;
81-
82-
case TypeCode.String:
54+
var typeCode = underlyingType.GetTypeCode();
55+
switch (typeCode)
56+
{
57+
case TypeCode.Boolean:
58+
value = DeserializeBooleanHelper(scalar.Value);
59+
break;
60+
61+
case TypeCode.Byte:
62+
case TypeCode.Int16:
63+
case TypeCode.Int32:
64+
case TypeCode.Int64:
65+
case TypeCode.SByte:
66+
case TypeCode.UInt16:
67+
case TypeCode.UInt32:
68+
case TypeCode.UInt64:
69+
value = DeserializeIntegerHelper(typeCode, scalar.Value);
70+
break;
71+
72+
case TypeCode.Single:
73+
value = Single.Parse(scalar.Value, YamlFormatter.NumberFormat);
74+
break;
75+
76+
case TypeCode.Double:
77+
value = Double.Parse(scalar.Value, YamlFormatter.NumberFormat);
78+
break;
79+
80+
case TypeCode.Decimal:
81+
value = Decimal.Parse(scalar.Value, YamlFormatter.NumberFormat);
82+
break;
83+
84+
case TypeCode.String:
85+
value = scalar.Value;
86+
break;
87+
88+
case TypeCode.Char:
89+
value = scalar.Value[0];
90+
break;
91+
92+
case TypeCode.DateTime:
93+
// TODO: This is probably incorrect. Use the correct regular expression.
94+
value = DateTime.Parse(scalar.Value, CultureInfo.InvariantCulture);
95+
break;
96+
97+
default:
98+
if (expectedType == typeof(object))
99+
{
100+
// Default to string
83101
value = scalar.Value;
84-
break;
85-
86-
case TypeCode.Char:
87-
value = scalar.Value[0];
88-
break;
89-
90-
case TypeCode.DateTime:
91-
// TODO: This is probably incorrect. Use the correct regular expression.
92-
value = DateTime.Parse(scalar.Value, CultureInfo.InvariantCulture);
93-
break;
94-
95-
default:
96-
if (expectedType == typeof(object))
97-
{
98-
// Default to string
99-
value = scalar.Value;
100-
}
101-
else
102-
{
103-
value = TypeConverter.ChangeType(scalar.Value, expectedType);
104-
}
105-
break;
106-
}
102+
}
103+
else
104+
{
105+
value = TypeConverter.ChangeType(scalar.Value, expectedType);
106+
}
107+
break;
107108
}
108109
return true;
109110
}

0 commit comments

Comments
 (0)