FastObjectNotation.Native.Runtime
0.4.0
dotnet add package FastObjectNotation.Native.Runtime --version 0.4.0
NuGet\Install-Package FastObjectNotation.Native.Runtime -Version 0.4.0
<PackageReference Include="FastObjectNotation.Native.Runtime" Version="0.4.0" />
<PackageVersion Include="FastObjectNotation.Native.Runtime" Version="0.4.0" />
<PackageReference Include="FastObjectNotation.Native.Runtime" />
paket add FastObjectNotation.Native.Runtime --version 0.4.0
#r "nuget: FastObjectNotation.Native.Runtime, 0.4.0"
#:package FastObjectNotation.Native.Runtime@0.4.0
#addin nuget:?package=FastObjectNotation.Native.Runtime&version=0.4.0
#tool nuget:?package=FastObjectNotation.Native.Runtime&version=0.4.0
FON — Fast Object Notation
FON is a fast, human-readable serialization format — a compact alternative to JSON for record-style data. Each line in a .fon file is one self-describing record of typed key=type:value pairs. This library provides native-speed serialization and deserialization for .NET, backed by a native core that parallelizes across CPU cores.
Features
- High performance — parallel serialization/deserialization across CPU cores, ~2 GB/s throughput
- Simple, human-readable format — typed
key=type:valuepairs, one record per line - Cross-platform — Windows, Linux, macOS (x64 and ARM64)
- Deterministic memory management —
FonDumpandFonCollectionareIDisposableand report their native memory footprint to the GC, so they're reclaimed promptly even without an explicitDispose
Installation
dotnet add package FastObjectNotation --version 0.4.0
dotnet add package FastObjectNotation.Native --version 0.3.0
FastObjectNotation is the library itself; FastObjectNotation.Native bundles the native runtime for every supported platform (Windows, Linux, Linux musl, macOS — x64 and ARM64). Both are required — there's no managed-only mode.
If you only need one platform, install FastObjectNotation.Native.Runtime plus the single matching FastObjectNotation.Native.{rid} package instead of the all-platforms meta-package (see Package Structure).
Quick Start
using FON.Core;
using FON.Types;
// Create a collection
using var collection = new FonCollection();
collection.Add("id", 42);
collection.Add("name", "Test Item");
collection.Add("price", 99.99);
collection.Add("active", true);
collection.Add("tags", new List<string> { "sale", "featured" });
// Serialize to string
var text = Fon.SerializeToString(collection);
// Result: id=i:42,name=s:"Test Item",price=d:99.99,active=b:1,tags=s:["sale","featured"]
// Create a dump (multiple records)
using var dump = new FonDump();
dump.TryAdd(0, collection);
dump.TryAdd(1, new FonCollection { { "id", 1 }, { "text", "Hello" } });
dump.TryAdd(2, new FonCollection { { "id", 2 }, { "text", "World" } });
// Serialize to file (auto-selects the best method)
await Fon.SerializeToFileAutoAsync(dump, new FileInfo("data.fon"));
// Deserialize from file
using var loaded = await Fon.DeserializeFromFileAutoAsync(new FileInfo("data.fon"));
// Access data
foreach (var (key, record) in loaded) {
var id = record.Get<int>("id");
Console.WriteLine($"Record {key}: id={id}");
}
You can also parse and serialize in memory, without touching the filesystem:
using var dump = Fon.Deserialize(text);
using var record = Fon.DeserializeCollection("id=i:1,name=s:\"Bob\"");
Disposal
FonDump and FonCollection wrap a native handle and implement IDisposable. Wrap them in using so the native memory is freed deterministically:
using var dump = await Fon.DeserializeFromFileAutoAsync(file);
If you forget, the handle's critical finalizer still frees the native memory eventually, and the GC is told about the native memory via GC.AddMemoryPressure so it collects promptly rather than waiting on managed-heap pressure alone — but an explicit using is always preferable for predictable cleanup.
A FonCollection obtained from another one — via Get<FonCollection>(key), a List<FonCollection> element, or dump enumeration — is a borrowed view into its parent's native memory. Don't use it after the parent is disposed. Nesting a FonCollection into another (Add(key, childCollection), or into a FonDump) transfers ownership: the child becomes part of the parent's tree and disposing it separately afterward is a safe no-op.
The native store is append-only: overwriting an existing key/id or calling Remove throws NotSupportedException.
Supported Types
| Type | Code | Example |
|---|---|---|
byte |
e |
count=e:255 |
short |
t |
year=t:2024 |
int |
i |
id=i:42 |
uint |
u |
flags=u:12345 |
long |
l |
timestamp=l:1234567890 |
ulong |
g |
bignum=g:18446744073709551615 |
float |
f |
ratio=f:3.14 |
double |
d |
precise=d:3.141592653589793 |
string |
s |
name=s:"Hello" |
bool |
b |
active=b:1 |
RawData |
r |
data=r:"nm=QNzv..." |
FonCollection |
o |
user=o:{id=i:1,name=s:"Bob"} |
Numeric types support arrays (values=i:[1,2,3,4,5]), and nested objects support arrays of objects (items=o:[{id=i:1},{id=i:2}]). List<string> and List<bool> can be built and read back in memory, and serialize to valid FON text, but that text cannot currently be parsed back — the underlying parser only accepts array syntax for numeric element types. Prefer scalar string/bool fields, or a nested object, where a round-trip through text is needed.
Format Specification
FON uses a simple, human-readable format:
key=type:value,key2=type2:value2
Each line in a .fon file represents one record. Records are indexed by line number (0-based).
Examples
# Simple values
name=s:"John",age=i:30,balance=d:1234.56
# Arrays
scores=i:[95,87,92,88]
# Binary data (Z85 encoded)
image=r:"nm=QNzv..."
# Nested objects
user=o:{id=i:42,name=s:"Bob",addr=o:{city=s:"NY",zip=i:10001}}
# Arrays of objects
items=o:[{id=i:1,qty=i:5},{id=i:2,qty=i:3}]
# Empty object and empty array of objects
empty=o:{},none=o:[]
API Reference
Serialization
// Serialize a single record to a string
string text = Fon.SerializeToString(collection);
// Serialize an entire dump to a string
string text = Fon.SerializeToString(dump);
// Auto-select best method based on data size (recommended)
await Fon.SerializeToFileAutoAsync(dump, file);
// Pipeline / Chunked / plain variants also exist for source compatibility;
// all route through the same native file writer.
await Fon.SerializeToFilePipelineAsync(dump, file);
await Fon.SerializeToFileChunkedAsync(dump, file, chunkSize: 1000);
await Fon.SerializeToFileAsync(dump, file);
Deserialization
// In memory
FonDump dump = Fon.Deserialize(text);
FonDump dump = Fon.Deserialize(utf8Bytes);
FonCollection record = Fon.DeserializeCollection(text);
// Auto-select best method based on file size (recommended)
var dump = await Fon.DeserializeFromFileAutoAsync(file);
// Async variants also exist for source compatibility; all route through
// the same native file parser.
var dump = await Fon.DeserializeFromFileAsync(file);
var dump = await Fon.DeserializeFromFileChunkedAsync(file, chunkSize: 10000);
Configuration
// Automatically decompress RawData during deserialization
Fon.DeserializeRawUnpack = true;
// Maximum bracket nesting depth (default: 64)
Fon.MaxDepth = 64;
Package Structure
| Package | Description |
|---|---|
FastObjectNotation |
The library — FonDump, FonCollection, RawData, Fon |
FastObjectNotation.Native |
Meta-package that includes native binaries for every supported platform |
FastObjectNotation.Native.Runtime |
Managed P/Invoke layer (included by FastObjectNotation.Native) |
FastObjectNotation.Native.win-x64 |
Windows x64 native binary |
FastObjectNotation.Native.win-arm64 |
Windows ARM64 native binary |
FastObjectNotation.Native.linux-x64 |
Linux x64 native binary |
FastObjectNotation.Native.linux-arm64 |
Linux ARM64 native binary |
FastObjectNotation.Native.linux-musl-x64 |
Alpine Linux x64 native binary |
FastObjectNotation.Native.linux-musl-arm64 |
Alpine Linux ARM64 native binary |
FastObjectNotation.Native.osx-x64 |
macOS x64 native binary |
FastObjectNotation.Native.osx-arm64 |
macOS ARM64 (Apple Silicon) native binary |
If the native library can't be found or loaded at runtime, calls into FonDump/FonCollection/Fon throw a DllNotFoundException — this almost always means the platform package for your RID isn't installed. In Docker/Alpine images, install the linux-musl-* packages, not linux-*.
Performance Tips
- Use Auto methods —
SerializeToFileAutoAsyncandDeserializeFromFileAutoAsynclet the native core pick the best strategy for the data size. - Adjust parallelism — pass
maxDegreeOfParallelismto control how many threads the native core uses:await Fon.SerializeToFileAutoAsync(dump, file, maxDegreeOfParallelism: 4); - Use RawData for binary — more efficient than encoding large binary blobs as strings.
- Dispose promptly —
usingaFonDump/FonCollectionfrees native memory immediately instead of waiting for a GC pass.
Building from Source
git clone --recurse-submodules https://github.com/FastObjectNotation/FON.net.git
cd FON.net
# Build the native core
cargo build --release --manifest-path FON.Native/Cargo.toml
# Build the library
dotnet build
# Run tests
dotnet test
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on FastObjectNotation.Native.Runtime:
| Package | Downloads |
|---|---|
|
FastObjectNotation.Native
Native acceleration for FON (Fast Object Notation). This meta-package includes native binaries for all supported platforms: Windows (x64, ARM64), Linux (x64, ARM64, musl), and macOS (x64, ARM64). Install alongside FastObjectNotation to enable native acceleration — the library auto-detects and uses it when available. |
GitHub repositories
This package is not used by any popular GitHub repositories.