1

I'm using YamlDotNet with an Azure Function v2 to serialise YAML from a markdown file (hosted on GitHub) to a .net object. I'm struggling with this error when attempting to deserialize the YAML string

Expected 'StreamEnd', got 'DocumentStart

I'm getting the markdown file content using HttpClient with a GET request to https://github.com/martinkearn/Content/raw/fd83bf8218b7c5e01f8b498e8a831bcd3fc3c961/Blogs/Test.md which returns a raw markdown file in the response body.

My Model is

public class Article
{
    public string Title { get; set; }
    public string Author { get; set; }
    public List<string> Categories { get; set; }
}

My YAML is

---
title: Test File 
author: Martin Kearn  
categories:
  - Test
  - GitHubCMS 
  - One More Tag
  - another tag
---

Here is my code

// get url from request body
var url = "https://raw.githubusercontent.com/martinkearn/Content/fd83bf8218b7c5e01f8b498e8a831bcd3fc3c961/Blogs/Test.md";

// get raw file and extract YAML
using (var client = new HttpClient())
{
    //setup HttpClient
    client.BaseAddress = new Uri(url);
    client.DefaultRequestHeaders.Add("User-Agent", "ExtractYAML Function");

    //setup httpContent object
    var response = await client.GetAsync(url);

    string rawFile = await response.Content.ReadAsStringAsync();
    using (var r = new StringReader(rawFile))
    {
        var deserializer = new DeserializerBuilder()
            .WithNamingConvention(new CamelCaseNamingConvention())
            .Build();

        //This line is causing Expected 'StreamEnd', got 'DocumentStart'
        var article = deserializer.Deserialize<Article>(r);
    }
}
Martin Kearn
  • 2,313
  • 1
  • 21
  • 35

1 Answers1

1

Your actual downloaded file contains:

---
title: Test File 
author: Martin Kearn  
categories:
  - Test
  - GitHubCMS 
  - One More Tag
  - another tag
---

# Test file

The --- is the end-of-directives marker, which is optional if you don't have any directives ( %YAML 1.2, %TAG .... ).

Since you have an empty line after the second directive, this is counted as if your second document contained

---
null
# Test file

You should at least get rid of that empty line and possible remove the second end-of-directives marker, putting the comment at the end of the first document

The end-of-document indicator in YAML is ... at the beginning of a line.

Make your file read:

title: Test File 
author: Martin Kearn  
categories:
  - Test
  - GitHubCMS 
  - One More Tag
  - another tag
# Test file

or at most:

---
title: Test File 
author: Martin Kearn  
categories:
  - Test
  - GitHubCMS 
  - One More Tag
  - another tag
# Test file
Anthon
  • 69,918
  • 32
  • 186
  • 246
  • Thank you …. I want to use YAML as a metadata block at the start of a Markdown file which will have other Markdown content in it (GitHub flavoured Markdown). What is the correct way to structure this? I've updated the file listed in the regional question to show more markdown to show what I mean – Martin Kearn Nov 12 '18 at 16:53
  • I've managed to get it working by chopping off the markdown content and leaving just eth yaml which can then be serialised using `var yaml = response.Substring(0, response.LastIndexOf("---"));` … is this what I need to do? Does YamlDotNet not handle documents that contain things other than YAML? – Martin Kearn Nov 12 '18 at 17:00
  • I don't know about YamlDotnet, but every other parser that I have used needs to be presented with A) just YAML B) needs to be told up front whether one, or multiple documents are available in the stream. They all require splitting of a YAML "header" and then parsing just the header – Anthon Nov 13 '18 at 06:02
  • OK, thank you. between your main answer and the comments thread, we've got the answer I think; The parser needs to be presented with just YAML and it should be valid YAML without `---` in the wrong place. I can't really mark your answer as 'the' answer as it does not tell the full story to anyone from the future. If you can update it to include the details about only presenting YAML and perhaps include the line of code I mentioned, I'll mark it as the answer. Thank you – Martin Kearn Nov 13 '18 at 12:07