4

I'm using C# and I have a YAML file I want to deserialize.

I've looked at using YamlDotNet, and it looks like it's pretty decent, but I can't find how to handle this situation.

The YAML text I am working with has the following format:

1:
    id: 1
    name: foo
2:
    id: 2
    name: foo

I wish it looked like this instead, but it doesn't:

- id: 1
  name: foo
- id: 2
  name: foo

I can of course revert to doing everything much more manually, by looping over each node and manually creating the data object instances, but it seems like there should still be a way to have the ease of use from YamlDotNet while handling this annoying data structure.

I'm open to suggestions for other YAML parsing libraries in .NET.

MarredCheese
  • 17,541
  • 8
  • 92
  • 91
  • 2
    Your ideal format is not a valid YAML file, you cannot have two keys with the same value in one mapping. More appropriate would be a toplevel sequence with mappings as elements – Anthon Dec 14 '16 at 15:47
  • @Anthon Fair point! As you can probably tell I don't know much about YAML. –  Dec 14 '16 at 15:49
  • 1
    Would it be of interest to rewrite/reformat the file. Using Python and ruamel.yaml (of which I am the author), that is trivial, even preserving comments after the original key-value pairs. You could even call the python program to do the preprocessing from your C# code. – Anthon Dec 14 '16 at 19:38
  • Thanks for the suggestion, it's certainly an option. I found, and Antoine Aubry suggested, tweaks to the deserialization objects that will handle my case and I feel they're a better option for what I'm doing. But I'll keep ruamel.yaml in mind if I have YAML issues to solve in the future. –  Dec 15 '16 at 10:41

2 Answers2

6

I found the answer in another SO question: Seeking guidance reading .yaml files with C#

By deserializing to Dictionary<int, Item> I can successfully handle this data structure.

deserializer.Deserialize<Dictionary<int, Item>>(textReader);
Community
  • 1
  • 1
3

If you use a list, as your edit, you can deserialize that file easily using code similar to this:

class MyObject {
    public int Id { get; set; }
    public string Name { get; set; }
}

var deserializer = new DeserializerBuilder()
     .WithNamingConvention(new CamelCaseNamingConvention())
     .Build();

var result = deserializer.Deserialize<List<MyObject>>(File.OpenText("myfile.yml"));

Note: I am typing on a phone and can't test the code. It should be mostly correct but I haven't tested it.

Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
  • I tried deserializing to a `List<>` but I got the following exception: `Additional information: (Line: 1, Col: 1, Idx: 0) - (Line: 1, Col: 1, Idx: 0): Expected 'SequenceStart', got 'MappingStart' (at Line: 1, Col: 1, Idx: 0).` Deserializing to a Dictionary<> works though ... which is what you suggested in the other thread I found. So thank you! If you want to change this to using `Dictionary<>` I'll happily delete my answer and accept yours (since you're the original source anyway). –  Dec 15 '16 at 11:12
  • The List<> is for your updated code, which is more appropriate to represent that information: `- id: 1 name: foo - id: 2 name: foo` – Antoine Aubry Dec 15 '16 at 23:04
  • My ideal data is what I wish I had, but I don't have it. I'm stuck with the data the way it is. Well, not stuck, but I'd rather use Dictionary<> than mess about with transforming the data. –  Dec 16 '16 at 08:35