Как Пропустить Пустые Коллекции в Yamldotnet - PullRequest
1 голос
/ 02 июня 2019

Я пытаюсь выяснить , как пропустить сериализацию пустых коллекций, используя YamlDotNet . Я экспериментировал как с пользовательским ChainedObjectGraphVisitor , так и IYamlTypeConverter . Я новичок в использовании YamlDotNet и у меня есть некоторые пробелы в знаниях здесь.

Ниже приведена моя реализация для шаблона посетителя, которая приводит к ошибке YamlDotNet.Core.YamlException «Ожидаемый скаляр, SEQUENCE-START, MAPPING-START или ALIAS получил ошибку MappingEnd» . Я вижу некоторый онлайн-контент для MappingStart / MappingEnd, но я не уверен, как он вписывается в то, что я пытаюсь сделать (устранить беспорядок в большом количестве пустых коллекций). Любые указатели в правильном направлении приветствуются.

Использование сериализатора:

var serializer = new YamlDotNet.Serialization.SerializerBuilder()
                .WithNamingConvention(new YamlDotNet.Serialization.NamingConventions.CamelCaseNamingConvention())
                .WithEmissionPhaseObjectGraphVisitor(args => new YamlIEnumerableSkipEmptyObjectGraphVisitor(args.InnerVisitor))
                .Build();

Реализация ChainedObjectGraphVisitor:

    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;
    }
}

1 Ответ

1 голос
/ 02 июня 2019

Я полагаю, что ответ также состоит в том, чтобы переопределить метод EnterMapping () в базовом классе с помощью логики, аналогичной той, что была сделана в методе Enter ():

        public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context)
    {
        bool retVal = false;

        if (value.Value == null)
            return 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.
            {   // Don't skip this item - serialize it as normal.
                retVal = base.EnterMapping(key, value, context);
            }
            // Else we have an empty collection and the initialized return value of false is correct.
        }
        else
        {   // Not a collection, normal serialization.
            retVal = base.EnterMapping(key, value, context);
        }

        return retVal;
    }
...