使用 YamlDotNet 序列化动态模型时更改用于所有多行字符串的标量样式

spa*_*lug 6 yaml yamldotnet

我使用以下代码片段将项目的动态模型序列化为字符串(最终导出到 YAML 文件)。

    dynamic exportModel = exportModelConvertor.ToDynamicModel(project);
    var serializerBuilder = new SerializerBuilder();
    var serializer = serializerBuilder.EmitDefaults().DisableAliases().Build();

    using (var sw = new StringWriter())
    {
        serializer.Serialize(sw, exportModel);
        string result = sw.ToString();
    }
Run Code Online (Sandbox Code Playgroud)

任何多行字符串,如下所示:

propertyName = "One line of text
followed by another line
and another line"
Run Code Online (Sandbox Code Playgroud)

以以下格式导出:

propertyName: >
  One line of text

  followed by another line

  and another line
Run Code Online (Sandbox Code Playgroud)

请注意额外的(不需要的)换行符。

根据这个YAML Multiline 指南,这里使用的格式是折叠块标量样式。有没有办法使用 YamlDotNet 将所有多行字符串属性的输出样式更改为文字块标量样式或流标量样式之一?

YamlDotNet文档展示了如何使用 WithAttributeOverride 将 ScalarStyle.DoubleQuoted 应用于特定属性,但这需要类名,并且要序列化的模型是动态的。这还需要列出要更改的每个属性(其中有很多)。我想立即更改所有多行字符串属性的样式。

spa*_*lug 8

为了回答我自己的问题,我现在已经弄清楚如何通过从ChainedEventEmitter类派生并覆盖void Emit(ScalarEventInfo eventInfo, IEmitter emitter). 请参阅下面的代码示例。

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

    public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter)
    {

        if (typeof(string).IsAssignableFrom(eventInfo.Source.Type))
        {
            string value = eventInfo.Source.Value as string;
            if (!string.IsNullOrEmpty(value))
            {
                bool isMultiLine = value.IndexOfAny(new char[] { '\r', '\n', '\x85', '\x2028', '\x2029' }) >= 0;
                if (isMultiLine)
                    eventInfo = new ScalarEventInfo(eventInfo.Source)
                    {
                        Style = ScalarStyle.Literal
                    };
            }
        }

        nextEmitter.Emit(eventInfo, emitter);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 与 SerializerBuilder 一起使用时的注意事项:`builder.WithEventEmitter(nextEmitter => new MultilineScalarFlowStyleEmitter(nextEmitter));` (2认同)