MiniBson.Source
1.1.3
See the version list below for details.
dotnet add package MiniBson.Source --version 1.1.3
NuGet\Install-Package MiniBson.Source -Version 1.1.3
<PackageReference Include="MiniBson.Source" Version="1.1.3"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="MiniBson.Source" Version="1.1.3" />
<PackageReference Include="MiniBson.Source"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add MiniBson.Source --version 1.1.3
#r "nuget: MiniBson.Source, 1.1.3"
#:package MiniBson.Source@1.1.3
#addin nuget:?package=MiniBson.Source&version=1.1.3
#tool nuget:?package=MiniBson.Source&version=1.1.3
MiniBson
MiniBson is a small BSON library for .NET. It combines a forward-only reader and writer with source-generated serialization, without using runtime reflection. The runtime library is designed for trimming and Native AOT.
Features
- Source-generated serialization for application types
- Low-level
BsonReaderandBsonWriterAPIs - No runtime reflection
netstandard2.0andnet8.0targets- No runtime dependency on
net8.0; onlySystem.Memoryonnetstandard2.0 - Conventional assembly and source-only NuGet packages
Installation
Choose the regular package for most applications:
dotnet add package MiniBson
Choose the source-only package to compile MiniBson directly into your assembly:
dotnet add package MiniBson.Source
The source-only package makes MiniBson types internal by default, preventing them from leaking into your public API or colliding with another embedded copy. Set MiniBsonPublic when public types are required.
Both packages include the source generator.
Source-generated serialization
Declare a partial context and register each type that can appear as a top-level value:
using MiniBson;
public sealed class Person
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public string[] Tags { get; set; } = [];
}
[BsonSerializable(typeof(Person))]
public partial class AppBsonContext
{
}
The generated context operates on BsonReader and BsonWriter instances, leaving ownership of streams and buffers with the caller:
var context = new AppBsonContext();
var original = new Person
{
Name = "Ada",
Age = 37,
Tags = ["compiler", "math"]
};
byte[] bson;
using (var stream = new MemoryStream())
{
using (var writer = new BsonWriter(stream, leaveOpen: true))
{
context.Serialize(original, writer);
}
bson = stream.ToArray();
}
using var reader = new BsonReader(bson);
var copy = (Person?)context.Deserialize(reader, typeof(Person));
Each context exposes:
void Serialize(object input, BsonWriter writer);
object? Deserialize(BsonReader reader, Type type);
Model behavior
- Top-level dispatch uses the exact runtime type. Register every concrete type passed directly to
SerializeorDeserialize. - Types referenced by properties are generated recursively, but are not automatically valid top-level values.
- All public, readable instance properties are serialized under their C# names. Inherited properties are included; a derived property wins when a name is hidden.
- Deserialization matches fields by name. Unknown fields are skipped, and missing fields retain their default values.
- Enums are stored by numeric value. Renaming a member is safe; changing its value changes the wire format.
Supported model types
| C# type | BSON representation |
|---|---|
bool |
Boolean |
byte, sbyte, short, ushort, int |
Int32 |
uint, long, ulong |
Int64 |
float, double |
Double |
string |
String |
DateTime |
UTC milliseconds since the Unix epoch |
Guid |
Binary, UUID subtype |
byte[], ReadOnlyMemory<byte> |
Binary |
| Enums | Int32 or Int64, according to the underlying type |
| One-dimensional arrays of supported values | Array |
| Other classes and records | Nested document |
| Nullable values and references | Their normal representation or Null |
Model limitations
- Collections such as
List<T>andDictionary<TKey, TValue>are not supported; use arrays. - Multidimensional and jagged arrays are not supported.
decimalis not supported because MiniBson has no Decimal128 mapping.- Non-record classes require an accessible parameterless constructor, and each discovered property must have a public
setorinitaccessor. - Records must be purely positional: their constructor must accept every discovered property in generated order.
- Two types with the same simple name can produce generated method-name collisions, even when their namespaces differ.
- A serialization context must be a partial class. A non-partial context is currently ignored without a diagnostic.
Unsupported members produce compiler error MINIBSON001 at the affected property, for example:
error MINIBSON001: MiniBson cannot serialize 'Order.Total': type 'decimal' is not supported
Changing the diagnostic severity does not add support. Generated code contains a runtime NotSupportedException fallback so an unsupported member cannot silently produce an empty value.
Low-level reader and writer
Use the low-level API when you need direct control over the BSON document or do not want model types.
Writing
using var stream = new MemoryStream();
using (var writer = new BsonWriter(stream, leaveOpen: true))
{
writer.WriteStartDocument();
writer.WriteString("name", "Ada");
writer.WriteInt32("age", 37);
writer.WriteBoolean("active", true);
writer.WriteStartArray("tags");
writer.WriteString("compiler");
writer.WriteString("math");
writer.WriteEndArray();
writer.WriteEndDocument();
}
byte[] bson = stream.ToArray();
Reading
using var reader = new BsonReader(bson);
reader.ReadStartDocument();
while (reader.Read())
{
switch (reader.CurrentName)
{
case "name":
Console.WriteLine(reader.ReadString());
break;
case "age":
Console.WriteLine(reader.ReadInt32());
break;
case "tags":
reader.ReadStartArray();
while (reader.Read())
{
Console.WriteLine(reader.ReadString());
}
reader.ReadEndDocument();
break;
default:
reader.Skip();
break;
}
}
reader.ReadEndDocument();
ReadEndDocument() closes the current reader context for either a document or an array.
Supported BSON values
| BSON value | Write API | Read API |
|---|---|---|
| Double | WriteDouble |
ReadDouble |
| String | WriteString |
ReadString |
| Document | WriteStartDocument, WriteEndDocument |
ReadStartDocument, ReadStartNestedDocument, ReadEndDocument |
| Array | WriteStartArray, WriteEndArray |
ReadStartArray, ReadEndDocument |
| Binary | WriteBinary |
ReadBinary, ReadBinaryAsMemory |
| ObjectId | WriteObjectId |
ReadObjectId |
| Boolean | WriteBoolean |
ReadBoolean |
| DateTime | WriteDateTime |
ReadDateTime |
| Null | WriteNull |
Inspect CurrentType or use ReadValue |
| Regular expression | WriteRegex |
ReadRegex |
| JavaScript | WriteJavaScript |
ReadJavaScript |
| Int32 | WriteInt32 |
ReadInt32 |
| Timestamp | WriteTimestamp |
ReadTimestamp |
| Int64 | WriteInt64 |
ReadInt64 |
| UUID | WriteGuid |
ReadGuid |
Stream-based readers and writers require seekable streams. BSON documents are length-prefixed, and skipping values also relies on changing the stream position.
Readers constructed from byte[] or ReadOnlyMemory<byte> use the supplied buffer directly. On that path, ReadBinaryAsMemory() returns a zero-copy slice that aliases the input; use ReadBinary() when an independent copy is needed.
Contributing
See DEVELOPMENT.md for repository structure, design notes, tests, and packaging commands.
Acknowledgments
A substantial part of the project was created with assistance from Claude.
License
MiniBson is available under the MIT License.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.