SharpYaml provides a JsonSerializer-style serialization API.

Basic usage

using SharpYaml;

var yaml = YamlSerializer.Serialize(new { Name = "Ada" });
var model = YamlSerializer.Deserialize<Person>(yaml);

Streams (UTF-8)

SharpYaml also provides Stream overloads (UTF-8) to avoid StreamReader/StreamWriter boilerplate:

using System.IO;
using SharpYaml;

using var stream = File.OpenRead("config.yml");
var config = YamlSerializer.Deserialize<MyConfig>(stream);

Buffer writers (zero-copy)

If you want to avoid string allocations when emitting YAML, you can write directly to an IBufferWriter<char>:

using System.Buffers;
using SharpYaml;

var buffer = new ArrayBufferWriter<char>();
YamlSerializer.Serialize(buffer, new { Name = "Ada" });

var yaml = new string(buffer.WrittenSpan);

Options

YamlSerializerOptions is immutable and can be cached and reused.

Common options:

using System.Text.Json;
using SharpYaml;

var options = new YamlSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    DefaultIgnoreCondition = YamlIgnoreCondition.WhenWritingNull,
};

Naming policy defaults

By default, YamlSerializerOptions.PropertyNamingPolicy is null, meaning CLR member names are used as-is for YAML mapping keys. This matches the default behavior of JsonSerializer (outside of ASP.NET defaults).

If you want camelCase keys, set PropertyNamingPolicy = JsonNamingPolicy.CamelCase.

Option reference

Option Default Meaning
PropertyNamingPolicy null Optional renaming for CLR member names.
DictionaryKeyPolicy null Optional renaming for dictionary keys during serialization.
PropertyNameCaseInsensitive false Case-insensitive property matching when reading.
PreferredObjectCreationHandling JsonObjectCreationHandling.Replace Controls whether members are replaced or populated during deserialization.
DefaultIgnoreCondition YamlIgnoreCondition.Never Skips null/default values when writing.
WriteIndented true Enables indentation.
IndentSize 2 Spaces per indent level when WriteIndented is enabled.
MappingOrder YamlMappingOrderPolicy.Declaration Preserves declaration order by default (diff-friendly in code review).
BlockSequenceMappingStyle YamlSequenceItemStyle.Compact Writes mappings in block sequences as - key: value by default.
BlockSequenceSequenceStyle YamlSequenceItemStyle.Expanded Controls whether nested sequences in block sequences start on the dash line or the following line.
Schema YamlSchemaKind.Core Controls scalar resolution rules (YAML 1.2).
DuplicateKeyHandling YamlDuplicateKeyHandling.Error Controls behavior when duplicate keys are encountered.
ReferenceHandling YamlReferenceHandling.None Enables anchor/alias preservation when needed.
ScalarStylePreferences new Controls scalar emission styles.
PolymorphismOptions new Controls polymorphism behaviors.
UnsafeAllowDeserializeFromTagTypeName false Allows tag-based activation by runtime type name (use only with trusted input).
TypeInfoResolver null Provides metadata (generated or custom) for reflection-free serialization.
SourceName null Used for error messages (file/path) when throwing YamlException.

Block sequence item style

Mappings written as block sequence items use compact style by default:

contexts:
  - name: default
    target: localhost

Set BlockSequenceMappingStyle = YamlSequenceItemStyle.Expanded to emit the first key on the following line instead. Nested sequences can be controlled separately with BlockSequenceSequenceStyle, and member-level overrides are available through YamlBlockSequenceItemStyleAttribute.

Object creation handling

SharpYaml follows the same default as System.Text.Json: member values are replaced unless you opt into population.

using System.Text.Json.Serialization;
using SharpYaml;

var options = new YamlSerializerOptions
{
    PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate,
};

You can also opt in per type or per member with JsonObjectCreationHandlingAttribute.

  • Replace is the default.
  • Populate reuses existing mutable reference-type members such as child objects, List<T>, IList<T>, ICollection<T>, Dictionary<TKey, TValue>, and IDictionary<TKey, TValue>.
  • Member-level [JsonObjectCreationHandling(...)] overrides the type or options default.
  • Struct members require a setter for Populate. A readonly struct property marked with Populate throws at runtime, matching System.Text.Json.

Reflection vs metadata

SharpYaml can resolve serialization metadata in two ways:

  1. Generated metadata using YamlSerializerContext and YamlTypeInfo<T> (recommended for NativeAOT).
  2. Reflection fallback (enabled by default).

If you disable reflection (see below), POCO/object mapping requires metadata via YamlTypeInfo<T> or YamlSerializerOptions.TypeInfoResolver. Built-in primitives and untyped containers remain supported without reflection.

AppContext.SetSwitch("SharpYaml.YamlSerializer.IsReflectionEnabledByDefault", false);

Working with a context

You can use a generated context in three styles:

  1. Use the generated YamlTypeInfo<T> property (recommended).
var yaml = YamlSerializer.Serialize(value, MyYamlContext.Default.MyConfig);
  1. Use the overloads that accept a context (needed for APIs that take Type).
var yaml = YamlSerializer.Serialize(value, typeof(MyConfig), MyYamlContext.Default);

Prefer the overloads that accept a YamlSerializerContext or a YamlTypeInfo<T> directly to avoid reflection and reduce configuration overhead.