A modern, multi‑format serialization platform for .NET. Built for AOT, performance, zero‑copy reading, and consistent APIs across binary, text, and tabular formats.
D20Tek.Serialization brings a unified architecture to serialization in .NET, inspired by the clarity of System.Text.Json and the extensibility of Serde. It provides:
- A shared core (metadata, converters, DOM, source generator contracts)
- High‑performance binary serializers (CBOR - Concise Binary Object Representation, TLV - Type Length Value, and custom binary formats)
- Human‑readable text serializers (YAML, TOML, JSON5, RON, XML‑subset)
- Row‑based tabular serializers (CSV, TSV, PSV, fixed‑width)
- A consistent developer experience across all formats
The initial release will support the shared core types and functionality and a CBOR binary serializer.
-
Unified architecture across all formats
Shared abstractions, options, converters, and source‑generated serializers. -
AOT‑friendly source generation
Deterministic, reflection‑free serializers for NativeAOT and trimming. -
Zero‑copy reading
Formats like CBOR and TLV expose rawReadOnlySpan<byte>slices without allocating. -
Advanced error reporting
JSONPath‑style error paths (e.g.,$.items[3].price) with expected/actual type info. -
Strict and lenient decoding modes
Choose between safety and flexibility. -
Format‑agnostic DOM
A sharedNodetree powers all document models (BinaryDocument, YamlDocument, etc.). -
Extensible converter model
Add custom converters for any type.
- D20Tek.Serialization.Core
Shared abstractions, metadata, converters, DOM, and source‑generator contracts.
- D20Tek.Serialization.Binary
High‑performance binary serializers including CBOR and TLV.
- D20Tek.Serialization.Text
YAML, TOML, JSON5, RON, XML‑subset.
- D20Tek.Serialization.Tabular
CSV, TSV, PSV, and fixed‑width row serializers.
D20Tek.Serialization/
│
├── src/
│ ├── D20Tek.Serialization.Core/
│ ├── D20Tek.Serialization.Binary/
│ ├── D20Tek.Serialization.Text/
│ └── D20Tek.Serialization.Tabular/
│
├── samples/
│ ├── BinarySamples/
│ ├── TextSamples/
│ ├── TabularSamples/
│ └── AotSamples/
│
├── docs/
│
└── tests/
├── CoreTests/
├── BinaryTests/
├── TextTests/
└── DelimitedTests/
dotnet add package D20Tek.Serialization.Binary[Serializable]
public sealed class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
var person = new Person { Name = "Alice", Age = 30 };
byte[] data = BinarySerializer.SerializeToByteArray(person);
Person? clone = BinarySerializer.Deserialize<Person>(data);Register a custom converter to control how specific types are serialized:
// A converter that writes strings as UPPER CASE
public sealed class UpperCaseStringConverter : Converter<string>
{
public override string Read(IFormatReader reader, SerializerOptions options)
=> reader.GetString();
public override void Write(IFormatWriter writer, string value, SerializerOptions options)
=> writer.WriteString(value.ToUpperInvariant());
}
var options = new BinarySerializerOptions();
options.Converters.Add(new UpperCaseStringConverter());
byte[] data = BinarySerializer.SerializeToByteArray("hello", options);
string? result = BinarySerializer.Deserialize<string>(data, options);
// result == "HELLO"Parse raw CBOR bytes and navigate without deserializing into a typed model:
using var doc = BinaryDocument.Parse(data);
string name = doc.RootElement["Name"].GetString();
int age = doc.RootElement["Age"].GetInt32();
foreach (var prop in doc.RootElement.EnumerateObject())
{
Console.WriteLine($"{prop.Name} = {prop.Value.ValueKind}");
}Just annotate your types with [Serializable] and enable the generator:
<ItemGroup>
<CompilerVisibleProperty Include="EmitCompilerGeneratedFiles" />
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</ItemGroup>D20Tek.Serialization supports two serialization paths with different AOT compatibility:
The source generator emits reflection‑free serializers and a registry for every [Serializable] type.
This path is fully compatible with NativeAOT publishing and IL trimming.
-
Annotate your types with
[Serializable]:[Serializable] public sealed class Customer { public int Id { get; set; } public string Name { get; set; } = string.Empty; }
-
Reference the generator in your project:
<ProjectReference Include="...\D20Tek.Serialization.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
-
Enable AOT in your project:
<PropertyGroup> <PublishAot>true</PublishAot> </PropertyGroup>
-
Serialize and deserialize — the generated serializer is discovered automatically:
byte[] data = BinarySerializer.SerializeToByteArray(customer); Customer? clone = BinarySerializer.Deserialize<Customer>(data);
The BinaryDocument / BinaryElement DOM is also fully AOT‑safe — it parses raw CBOR bytes
without reflection.
When no generated serializer or custom converter is registered for a type, BinarySerializer
falls back to a reflection‑based serializer. This path:
- Uses
TypeMetadataBuilderto discover members at runtime - Compiles accessor delegates via expression trees
- Is not compatible with NativeAOT or IL trimming
All reflection entry points are annotated with [RequiresUnreferencedCode] and
[RequiresDynamicCode], so the compiler will emit warnings if you call them in a trimmed context.
| Path | AOT‑Safe | Trimming‑Safe | How to Enable |
|---|---|---|---|
| Source‑generated serializer | ✅ | ✅ | [Serializable] + generator reference |
| Custom converter | ✅ | ✅ | Register via options.Converters |
| BinaryDocument DOM | ✅ | ✅ | BinaryDocument.Parse(bytes) |
| Reflection fallback | ❌ | ❌ | Automatic when no generator/converter found |
Documentation lives in the /docs folder and includes:
- architecture overview
- format specifications
- source generator design
- DOM model
- error reporting
- samples and tutorials
The /samples directory includes:
- Binary serialization examples
- YAML/TOML/CSV examples
- AOT‑friendly sample apps
- Format‑to‑format converters
- Performance benchmarks
Planned features include:
- Canonical/deterministic profiles
- CRDT‑friendly binary formats
- Schema generation (JSON Schema, TOML Schema, etc.)
- Enum tagging strategies
- Flattening and default value attributes
- Streaming serializers
- Zero‑copy DOM cursor
- Format‑to‑format transformation APIs
To contribute, provide feature ideas or bug reports in this repo Issues.
- A sample project template
Just tell me what direction you want to go next.