aaubry / YamlDotNet

YamlDotNet is a .NET library for YAML
MIT License
2.58k stars 484 forks source link

Null exception on enum values with an empty EnumMember #966

Closed welbertwpg closed 2 months ago

welbertwpg commented 2 months ago
Describe the bug The serializer throws a Null Exception when serializing enums that have the EnumMember attribute without a Value being specified. Exception details:   Name Value Type
  Message Object reference not set to an instance of an object. string
  StackTrace " at YamlDotNet.Core.Emitter.AnalyzeScalar(Scalar scalar)\r\n at YamlDotNet.Core.Emitter.AnalyzeEvent(ParsingEvent evt)\r\n at YamlDotNet.Core.Emitter.Emit(ParsingEvent event)\r\n at YamlDotNet.Serialization.EventEmitters.WriterEventEmitter.YamlDotNet.Serialization.IEventEmitter.Emit(MappingEndEventInfo eventInfo, IEmitter emitter)\r\n at YamlDotNet.Serialization.EventEmitters.ChainedEventEmitter.Emit(MappingEndEventInfo eventInfo, IEmitter emitter)\r\n at YamlDotNet.Serialization.ObjectGraphVisitors.EmittingObjectGraphVisitor.YamlDotNet.Serialization.IObjectGraphVisitor.VisitMappingEnd(IObjectDescriptor mapping, IEmitter context, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphVisitors.ChainedObjectGraphVisitor.VisitMappingEnd(IObjectDescriptor mapping, IEmitter context, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphVisitors.ChainedObjectGraphVisitor.VisitMappingEnd(IObjectDescriptor mapping, IEmitter context, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphVisitors.ChainedObjectGraphVisitor.VisitMappingEnd(IObjectDescriptor mapping, IEmitter context, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphVisitors.ChainedObjectGraphVisitor.VisitMappingEnd(IObjectDescriptor mapping, IEmitter context, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphTraversalStrategies.FullObjectGraphTraversalStrategy.TraverseProperties[TContext](IObjectDescriptor value, IObjectGraphVisitor1 visitor, TContext context, Stack1 path, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphTraversalStrategies.FullObjectGraphTraversalStrategy.TraverseObject[TContext](IPropertyDescriptor propertyDescriptor, IObjectDescriptor value, IObjectGraphVisitor1 visitor, TContext context, Stack1 path, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphTraversalStrategies.FullObjectGraphTraversalStrategy.Traverse[TContext](IPropertyDescriptor propertyDescriptor, Object name, IObjectDescriptor value, IObjectGraphVisitor1 visitor, TContext context, Stack1 path, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.ObjectGraphTraversalStrategies.FullObjectGraphTraversalStrategy.YamlDotNet.Serialization.IObjectGraphTraversalStrategy.Traverse[TContext](IObjectDescriptor graph, IObjectGraphVisitor`1 visitor, TContext context, ObjectSerializer serializer)\r\n at YamlDotNet.Serialization.SerializerBuilder.ValueSerializer.SerializeValue(IEmitter emitter, Object value, Type type)\r\n at YamlDotNet.Serialization.Serializer.EmitDocument(IEmitter emitter, Object graph, Type type)\r\n at YamlDotNet.Serialization.Serializer.Serialize(IEmitter emitter, Object graph)\r\n at YamlDotNet.Serialization.Serializer.Serialize(TextWriter writer, Object graph)\r\n at YamlDotNet.Serialization.Serializer.Serialize(Object graph)\r\n at Program.
$(String[] args) in C:\Users\...\ConsoleApp1\ConsoleApp1\Program.cs:line 10"
string

To Reproduce The code below reproduces the issue:

using System.Runtime.Serialization;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

var serializer = new SerializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .Build();

var obj = new TestClass() { TestEnum = TestEnum.Value1 };
var yaml = serializer.Serialize(obj);

Console.WriteLine(yaml);

public enum TestEnum
{
    [EnumMember]
    Value1,

    [EnumMember]
    Value2
}

public class TestClass
{
    public TestEnum TestEnum { get; set; }
}

Basically, create any enum with the [EnumMember] attribute and try to serialize an object with that.

EdwardCooke commented 2 months ago

Thanks for the easy reproduction code. I'll have a fix out in a bit. If there is no name set for the EnumMember I'm planning on just using the name of the enum value.

EdwardCooke commented 2 months ago

This will go out in the next release in a couple of weeks.

EdwardCooke commented 2 months ago

This is released.