Skip to content

Commit 78ff21e

Browse files
committed
Fix nullable struct serialization
Addresses #360
1 parent 78a57da commit 78ff21e

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

YamlDotNet.Test/Serialization/SerializationTestHelper.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ public enum EnumExample
141141
Two
142142
}
143143

144+
public struct StructExample
145+
{
146+
public int Value { get; set; }
147+
}
148+
144149
public enum SByteEnum : sbyte { Default, Sbyte }
145150
public enum ByteEnum : byte { Default, Byte }
146151
public enum Int16Enum : short { Default, Short }

YamlDotNet.Test/Serialization/SerializationTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,24 @@ public void RoundtripNullableEnums(EnumExample? value)
183183
result.Should().Be(value);
184184
}
185185

186+
[Fact]
187+
public void RoundtripNullableStructWithValue()
188+
{
189+
var value = new StructExample { Value = 2 };
190+
191+
var result = DoRoundtripFromObjectTo<StructExample?>(value);
192+
193+
result.Should().Be(value);
194+
}
195+
196+
[Fact]
197+
public void RoundtripNullableStructWithoutValue()
198+
{
199+
var result = DoRoundtripFromObjectTo<StructExample?>(null);
200+
201+
result.Should().Be(null);
202+
}
203+
186204
[Fact]
187205
public void SerializeCircularReference()
188206
{

YamlDotNet/Serialization/NodeDeserializers/ObjectNodeDeserializer.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ bool INodeDeserializer.Deserialize(IParser parser, Type expectedType, Func<IPars
4747
return false;
4848
}
4949

50-
value = objectFactory.Create(expectedType);
50+
// Strip off the nullable type, if present. This is needed for nullable structs.
51+
var implementationType = Nullable.GetUnderlyingType(expectedType) ?? expectedType;
52+
53+
value = objectFactory.Create(implementationType);
5154
while (!parser.TryConsume<MappingEnd>(out var _))
5255
{
5356
var propertyName = parser.Consume<Scalar>();
54-
var property = typeDescriptor.GetProperty(expectedType, null, propertyName.Value, ignoreUnmatched);
57+
var property = typeDescriptor.GetProperty(implementationType, null, propertyName.Value, ignoreUnmatched);
5558
if (property == null)
5659
{
5760
parser.SkipThisAndNestedEvents();

0 commit comments

Comments
 (0)