我试图找出如何跳过使用YamlDotNet序列化空集合。我已经尝试过定制的ChainedObjectGraphVisitor和IYamlTypeConverter。我刚开始使用YamlDotNet,这里有一些知识空白。
下面是我对访问者模式的实现,它导致了YamlDotNet.Core.YamlException “预期的标量、序列启动、映射-开始或别名,got”错误。我确实看到了一些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;
}
}发布于 2019-06-02 16:08:01
我相信答案也是用类似于Enter()方法中所做的逻辑覆盖基类中的EnterMapping()方法:
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;
}发布于 2020-11-08 10:47:10
最后,我上了下面的课:
using System.Collections;
using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.ObjectGraphVisitors;
sealed class YamlIEnumerableSkipEmptyObjectGraphVisitor : ChainedObjectGraphVisitor
{
public YamlIEnumerableSkipEmptyObjectGraphVisitor(IObjectGraphVisitor<IEmitter> nextVisitor): base(nextVisitor)
{
}
private bool IsEmptyCollection(IObjectDescriptor value)
{
if (value.Value == null)
return true;
if (typeof(IEnumerable).IsAssignableFrom(value.Value.GetType()))
return !((IEnumerable)value.Value).GetEnumerator().MoveNext();
return false;
}
public override bool Enter(IObjectDescriptor value, IEmitter context)
{
if (IsEmptyCollection(value))
return false;
return base.Enter(value, context);
}
public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context)
{
if (IsEmptyCollection(value))
return false;
return base.EnterMapping(key, value, context);
}
}发布于 2022-09-29 08:57:30
您可以指定DefaultValuesHandling
在序列化程序中:
var serializer = new SerializerBuilder()
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitEmptyCollections)
.Build(); 或在字段/属性的属性YamlMember中:
public class MyDtoClass
{
[YamlMember(DefaultValuesHandling = DefaultValuesHandling.OmitEmptyCollections)]
public List<string> MyCollection;
}https://stackoverflow.com/questions/56411304
复制相似问题