Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Literal scalar style ignored in case of leading space in line #458

Open
werwolfby opened this issue Dec 9, 2019 · 2 comments
Open

Literal scalar style ignored in case of leading space in line #458

werwolfby opened this issue Dec 9, 2019 · 2 comments

Comments

@werwolfby
Copy link

I can't find why when I specify string with leading space in some line it is stored as DoubleQuoted instead of Literal.

Example:

class Program
{
    static void Main(string[] args)
    {
        var serializer = new SerializerBuilder()
            .WithEventEmitter(e => new LiteralMultilineEventEmitter(e))
            .Build();

        var obj = "line with leading space \nother line";
        Console.WriteLine(serializer.Serialize(obj));
    }

    private class LiteralMultilineEventEmitter : ChainedEventEmitter
    {
        public LiteralMultilineEventEmitter(IEventEmitter nextEmitter) : base(nextEmitter)
        {
        }

        public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter)
        {
            if (eventInfo.Source.Type == typeof(string) && eventInfo.Source.Value is string value && value.Contains("\n"))
            {
                eventInfo.Style = ScalarStyle.Literal;
            }
            base.Emit(eventInfo, emitter);
        }
    }
}

Returns:

"line with leading space \nother line"

While if I change value obj value to:

var obj = "line with leading space\nother line";

without space then it is serialized right:

|-
  line with leading space
  other line

I've debug code to Emitter where I can see that this is expected behavior, but I can't find such behavior in documentation.

More over even if I will try to read this Literal string from YAML it will be deserialized right as expected:

    static void Main(string[] args)
    {
        var serializer = new SerializerBuilder()
            .WithEventEmitter(e => new LiteralMultilineEventEmitter(e))
            .Build();

        var obj = "line with leading space \nother line";
        Console.WriteLine(serializer.Serialize(obj));

        var yaml =
            "|-\r\n" +
            "  line with leading space \r\n" +
            "  other line";
        
        var deserializer = new DeserializerBuilder().Build();
        var deserializedValue = deserializer.Deserialize<string>(yaml);
        Console.WriteLine(deserializedValue);
        Console.WriteLine(deserializedValue == obj);
    }

With output:

line with leading space 
other line
True
@werwolfby
Copy link
Author

I've found the same code in PyYAML.

@stuartbean
Copy link

I found the same issue. It's due to the internal check for valid literal strings in Yaml not permitting spaces prior to line breaks. I wrote an event emitter to "clean" up these strings as we wanted all literal strings to appear that way and trailing space removal wouldn't break the data (it contained Html / JavaScript etc).

    public class LiteralScalarCleanerEmitter : ChainedEventEmitter
    {
        private static readonly Regex Pattern = new Regex(@"\s*$", RegexOptions.Compiled | RegexOptions.Multiline);

        public LiteralScalarCleanerEmitter(IEventEmitter nextEmitter)
            : base(nextEmitter)
        {
        }

        public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter)
        {
            if (eventInfo.Source.Type == typeof(string) && eventInfo.Source.ScalarStyle == ScalarStyle.Literal)
            {
                var value = (string)eventInfo.Source.Value;

                if (!string.IsNullOrEmpty(value))
                {
                    eventInfo.RenderedValue = Pattern.Replace(value, string.Empty);
                }
            }

            base.Emit(eventInfo, emitter);
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants