The C# YAML parser most .NET code uses is YamlDotNet, with more than 600 million NuGet downloads and targets from .NET Framework 4.7 to .NET 10. Its README lists YAML 1.2 for the parser but only YAML 1.1 for the emitter, and its typed deserializer reads yes as true. SharpYaml 3 has a System.Text.Json-style API and reads the YAML 1.2 Core schema. VYaml is built for speed and Unity. OneYaml pairs a System.Text.Json-style serializer with a YamlDocument that edits a file and keeps its comments, on .NET 8 and .NET 10. All four are permissively licensed.
Package facts are from each NuGet listing and README, read on 26 October 2026. Behavior was measured by running each package, and the program is below.
.NET YAML libraries at a glance
| Package, version (date) | License | Targets | API | YAML version, per its docs |
|---|---|---|---|---|
| YamlDotNet 18.1.0 (Jun 2026) | MIT | .NET Standard 2.0 and 2.1, .NET Framework 4.7, .NET 8, .NET 10 | DeserializerBuilder/SerializerBuilder, a YamlStream object model, low-level parser and emitter | Parser 1.1 and 1.2, emitter 1.1 (README) |
| SharpYaml 3.16.0 (Oct 2026) | MIT | .NET Standard 2.0, .NET 8, .NET 10 | System.Text.Json style: YamlSerializer, YamlSerializerOptions; scanner, parser, emitter and syntax tree | “YAML 1.2 Core Schema”, with Failsafe, JSON and Extended selectable (README) |
| VYaml 1.5.0 (Oct 2026) | MIT | .NET Standard 2.0 and 2.1, .NET 6, 8, 9; Unity | [YamlObject] partial types, source-generated; a UTF-8 parser and emitter | “YAML 1.2 mostly supported” (README) |
| OneYaml 1.2.1 (Oct 2026) | MIT OR Apache-2.0 | .NET 8, .NET 10 | System.Text.Json style YamlSerializer, plus a lossless YamlDocument with JSON Pointer edits and patches | 1.2, Core schema |
For native AOT, SharpYaml and OneYaml ship a source generator inside the main package, and VYaml generates code for [YamlObject] types. YamlDotNet’s generator is a separate package, Vecc.YamlDotNet.Analyzers.StaticGenerator.
The same file, read by three C# YAML libraries
YAML 1.1 read yes as a boolean and a leading zero as octal. YAML 1.2 has only true and false as booleans, and 0755 is the decimal 755. This program binds both forms to a typed class with each library:
using System.Text.Json; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; var readers = new (string Name, Func<string, Settings> Read)[] { ("YamlDotNet 18.1.0", yaml => new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build() .Deserialize<Settings>(yaml)), ("SharpYaml 3.16.0", yaml => SharpYaml.YamlSerializer.Deserialize<Settings>(yaml, new SharpYaml.YamlSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })!), ("OneYaml 1.2.1", yaml => OneYaml.YamlSerializer.Deserialize<Settings>(yaml)!), }; foreach (var (name, read) in readers) { Console.WriteLine($"{name}: {Show(() => read("enabled: yes").Enabled)}, {Show(() => read("mode: 0755").Mode)}"); } static string Show<T>(Func<T> get) { try { return $"{get()}"; } catch (Exception e) { return e.GetType().Name; } } class Settings { public bool Enabled { get; set; } public int Mode { get; set; } }
YamlDotNet 18.1.0: True, 493 SharpYaml 3.16.0: YamlException, 755 OneYaml 1.2.1: YamlException, 755
YamlDotNet reads the file as YAML 1.1: yes becomes true and 0755 becomes 493. SharpYaml and OneYaml read it as YAML 1.2: yes is refused as a boolean, and 0755 is 755. Neither answer is wrong for every project, but you should know which one you get. OneYaml’s error names the line, the column and the JSON Pointer of the value: The value 'yes' cannot be read as a boolean. (line 1, column 10, path /enabled). VYaml isn’t in the run: its typed serializer works through source-generated [YamlObject] partial types, which needs a different program.
Read and edit YAML in C# with OneYaml
dotnet new console -o YamlStart cd YamlStart dotnet add package OneYaml --version 1.2.1
YamlSerializer.Deserialize<T> binds YAML to classes and records the way JsonSerializer binds JSON, with keys in camel case by default. To change a file that people also edit by hand, parse it into a YamlDocument:
using OneYaml; const string Src = """ # Deploy settings name: api replicas: 2 # raised by the release job ports: [80] """; // Typed read, the way System.Text.Json works. Keys bind in camel case. var cfg = YamlSerializer.Deserialize<Config>(Src)!; Console.WriteLine($"{cfg.Name}: {cfg.Replicas} replicas on {string.Join(", ", cfg.Ports)}"); // Edit the same text: only the values you set change. using var doc = YamlDocument.Parse(Src); doc.Set("/replicas", 3); doc.Add("/ports/-", 443); Console.WriteLine(doc); record Config(string Name, int Replicas, List<int> Ports);
api: 2 replicas on 80 # Deploy settings name: api replicas: 3 # raised by the release job ports: [80, 443]
The comment after replicas stays, and the new port joins the flow list in its own style. YamlSerializerOptions takes naming policies, ignore conditions, converters and the System.Text.Json attributes (serializer). The getting started guide covers writing YAML and patches, and the classes recipe and reading YAML without a class go further.
What each C# YAML library is for
YamlDotNet
The default choice for years, and the widest reach: .NET Standard 2.0, .NET Framework and current .NET, plus a Unity Asset Store package. It has builders for the serializer, an object model “similar to XmlDocument”, and low-level parsing and emitting. Its node deserializers can be replaced or extended to change how binding works, as its samples show for validation. Choose it for older frameworks, for those extension points, or when the code already works.
SharpYaml
Version 3 is a redesign with a System.Text.Json-style API, YAML 1.2 Core by default with other schemas selectable, System.Text.Json attribute support, a source generator in the package, and public scanner, parser, emitter and syntax tree APIs. Choose it for System.Text.Json-style code that also has to run on .NET Standard 2.0, or when you need a schema other than Core.
VYaml
A low-allocation library that works on UTF-8 bytes directly, built for .NET and Unity, including Unity’s own serialized YAML. Choose it for Unity, or when allocation per read matters most.
OneYaml
The System.Text.Json shape for YAML 1.2, plus edits in place: YamlDocument writes a new value in the old one’s style and keeps every other byte, comments included (edit YAML without losing comments). It applies RFC 6902 JSON Patch and RFC 7396 Merge Patch to the YAML text (JSON Patch for YAML), bounds depth, alias expansion and integer size by default with a YamlLimits.Untrusted preset (untrusted input), and has no dependencies outside .NET. Speed and memory against the other libraries are on the performance page, which lists the files where OneYaml was slower.
When OneYaml is not the right fit
- .NET Framework, .NET Standard or Unity: OneYaml runs on .NET 8 and .NET 10 only.
- Comments as data:
YamlDocumentkeeps comments through edits, but it can’t read, add or move them. - A public streaming parser: OneYaml exposes its reader only inside a converter. YamlDotNet, SharpYaml and VYaml have public pull parsers.
- Schemas other than Core: OneYaml reads the Core schema only.
- A long track record: OneYaml 1.0.0 was released in October 2026.
How to choose a C# YAML library
- New code on .NET 8 or later that reads configuration, or edits files people maintain: OneYaml.
- System.Text.Json-style code that must also target .NET Standard 2.0: SharpYaml.
- Unity: VYaml or YamlDotNet.
- Existing YamlDotNet code: keep it, or swap to
OneYaml.Compat.YamlDotNet, which keeps the builder calls (replacing YamlDotNet). - Existing SharpYaml code: keep it, or use
OneYaml.Compat.SharpYaml(from SharpYaml).
For a fuller side-by-side, including where the others win, see how OneYaml compares. All three oneyaml languages are on the oneyaml home page.