3

When writing a sequence in an IYamlTypeConverter you might use some code like this:

public class MyObjectConverter : IYamlTypeConverter {
    public MyObjectConverter() {}

    public bool Accepts(Type type) { return typeof(IMyObject) == type || typeof(IMyObject[]) == type; }
    public object ReadYaml(IParser parser, Type type) { return null; }
    public void WriteYaml(IEmitter emitter, object value, Type type) {
        var itemVal = value as IMyObject;
        if (itemVal != null)
            emitter.Emit(new Scalar(itemVal.GetID()));
        else {
            var arrayVal = value as IMyObject[];
            emitter.Emit(new SequenceStart(null, null, true, SequenceStyle.Block));
            if (arrayVal != null) {
                foreach (var item in arrayVal)
                    if (item != null) emitter.Emit(new Scalar(item.GetID()));
                    else              emitter.Emit(new Scalar("null"));
            }
            emitter.Emit(new SequenceEnd());
        }
    }
}

By calling emitter.Emit(new Scalar("null")) you would get a 'null' entry in the sequence, but if you leave the serialization up to YamlDotNet, it would be serialized as '' (empty string).

How do you output a null value in a sequence as an empty string when writing a custom IYamlTypeConverter?

Steinbitglis
  • 2,482
  • 2
  • 27
  • 40

2 Answers2

3

One way to achieve this is to create a custom IEventEmitter that will add this logic:

public class NullStringsAsEmptyEventEmitter : ChainedEventEmitter
{
    public NullStringsAsEmptyEventEmitter(IEventEmitter nextEmitter)
        : base(nextEmitter)
    {
    }

    public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter)
    {
        if (eventInfo.Source.Type == typeof(string) && eventInfo.Source.Value == null)
        {
            emitter.Emit(new Scalar(string.Empty));
        }
        else
        {
            base.Emit(eventInfo, emitter);
        }
    }
}

You then register it like this:

var serializer = new SerializerBuilder()
    .WithEventEmitter(nextEmitter => new NullStringsAsEmptyEventEmitter(nextEmitter))
    .Build();

Here's a fiddle with this code

Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
  • Hmm.. I seem to have accepted this answer too fast. I'm still getting a nullreference in YamlDotNet.Core.Emitter.AnalyzeScalar. Also, I think the fiddle link doesn't lead to the code you intended to show. – Steinbitglis Nov 06 '17 at 13:44
  • I've updated the fiddle's code. I must have forgotten to save or something. Can you provide a stack trace with the NullReferenceException ? – Antoine Aubry Nov 06 '17 at 14:20
0

It seems you can represent a null value simply with '~', according to http://www.yaml.org/refcard.html