0

I have a requirement of parsing yaml documents including comments, my yaml file looks like this

Prerequisite_Services:
- Service_Name: abc
Workflows:
- Workflow: workflow1
  Service:
  - Service_Name: abc1
  - Service_Name: abc2
# - Service_Name: abc3
- Workflow: xyz
  Service:
  - Service_Name: def1
  - Service_Name: def2
  - Service_Name: def3
  - Service_Name: def4
# - Service_Name: def5
  - Service_Name: def6

i need to parse both service abc3 and def5 i tried below codes

using System;
using System.Collections.Generic;
using System.IO;
using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace YamlTesting
{
public class ConfigReader
{
    private static string _filePath = string.Empty;
    private static Workflows _workFlows = null;

    public static void Main()
    {
        _filePath = "D:\\testdata.yaml";
        if (!File.Exists(_filePath))
        {
            throw new FileNotFoundException("Missing File : Check the source folder for Workflow file.");
        }
        try
        {
            using (var input = File.OpenText(_filePath))
            {
                var parser = new Parser(new Scanner(new StreamReader(_filePath), skipComments: false));
                var deserializer = new DeserializerBuilder()
                    .WithNamingConvention(new CamelCaseNamingConvention())
                    .Build();
                _workFlows = deserializer.Deserialize<Workflows>(parser);
            }
        }

        catch (SyntaxErrorException e)
        {
            throw new Exception("Sytanx Error : Check the syntax in the Workflow file.", e);
        }
        catch (YamlException e)
        {
            throw new Exception("Invalid workflow identified. Check the Workflow file.", e);
        }
    }
}

public class Workflows
{
    [YamlMember(Alias = "Prerequisite_Services", ApplyNamingConventions = false)]
    public List<Servicess> PreRequisiteServices { get; set; }

    [YamlMember(Alias = "Workflows", ApplyNamingConventions = false)]
    public List<WorkFlow> WorkFlows { get; set; }
}

public class WorkFlow
{
    [YamlMember(Alias = "Workflow", ApplyNamingConventions = false)]
    public string WorkflowName { get; set; }
    [YamlMember(Alias = "Service", ApplyNamingConventions = false)]
    public List<Servicess> Service { get; set; }
}

public class Servicess
{
    [YamlMember(Alias = "Service_Name", ApplyNamingConventions = false)]
    public string ServiceName { get; set; }
}

I am getting an error when running above code "got comment instead of scalar", how i can read the comment? i need this comments as this is config file and i need to replace it and i can't ignore comments

Prashant
  • 51
  • 9
  • The comments make that non-yaml data. You could build a pre-processor (just remove the `#` in column 0). But that might conflict with other (genuine) comments. Also, do you want to write those lines back? As comments? – H H Feb 15 '19 at 13:05
  • Yes I want to write it back as comments. – Prashant Feb 15 '19 at 13:12
  • So that makes it a non-yaml problem... Maybe simple string ops or regex are an option. – H H Feb 15 '19 at 13:19
  • @HenkHolterman thanks for letting me know, it was typo, I have corrected it – Prashant Feb 15 '19 at 13:32
  • @HenkHolterman I can't use string ops, as I will be having new config file. I will be required to merge both yaml files and have to persists comments – Prashant Feb 15 '19 at 13:33
  • You didn't explain "both" yaml files or "merge". Post sample input and outputs, maybe someone will have an idea. – H H Feb 15 '19 at 13:44

2 Answers2

1

The Deserializer doesn't know hot to handle comments. If you really need to preserve comments, you we have to parse the stream using IParser directly. You could probably extend the Deserializer to be able to recognize the comments, but you would have the problem that it would need some place to store them somewhere.

Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
1

I was not able to parse the comments, so I have added the following code that I have found at another discussion for files:

public void AddNotParsedData (string fich)
{
      string[] full_file = File.ReadAllLines(fich);
      List<string> l = new List<string>();
      l.AddRange(full_file);

      l.Insert(0, "Comment1");
      l.Insert(9, "Comment2");
      
      File.WriteAllLines(fich, l.ToArray());
}

This is not dynamic, but it is a workaround that can be used in case yaml has always the same format.

Benjamin Zach
  • 1,452
  • 2
  • 18
  • 38
Mário Cera
  • 25
  • 1
  • 5