I'm trying to figure out how to skip serializing empty collections using YamlDotNet. I have experimented with both a custom ChainedObjectGraphVisitor and IYamlTypeConverter. I'm new to using YamlDotNet and have some knowledge gaps here.
Below is my implementation for the visitor pattern, which results in a YamlDotNet.Core.YamlException "Expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, got MappingEnd" error. I do see some online content for MappingStart/MappingEnd, but I'm not sure how it fits into what I'm trying to do (eliminate clutter from lots of empty collections). Any pointers in the right direction are appreciated.
Instantiating the serializer:
var serializer = new YamlDotNet.Serialization.SerializerBuilder()
.WithNamingConvention(new YamlDotNet.Serialization.NamingConventions.CamelCaseNamingConvention())
.WithEmissionPhaseObjectGraphVisitor(args => new YamlIEnumerableSkipEmptyObjectGraphVisitor(args.InnerVisitor))
.Build();
ChainedObjectGraphVisitor implementation:
public sealed class YamlIEnumerableSkipEmptyObjectGraphVisitor : ChainedObjectGraphVisitor
{
public YamlIEnumerableSkipEmptyObjectGraphVisitor(IObjectGraphVisitor<IEmitter> nextVisitor)
: base(nextVisitor)
{
}
public override bool Enter(IObjectDescriptor value, IEmitter context)
{
bool retVal;
if (typeof(System.Collections.IEnumerable).IsAssignableFrom(value.Value.GetType()))
{ // We have a collection
var enumerableObject = (System.Collections.IEnumerable)value.Value;
if (enumerableObject.GetEnumerator().MoveNext()) // Returns true if the collection is not empty.
{ // Serialize it as normal.
retVal = base.Enter(value, context);
}
else
{ // Skip this item.
retVal = false;
}
}
else
{ // Not a collection, normal serialization.
retVal = base.Enter(value, context);
}
return retVal;
}
}