High-performance serialization library for .NET with parallel processing and optional native acceleration. A fast alternative to JSON for .NET applications.
- High Performance - Parallel serialization/deserialization with SIMD-optimized parsing
- Zero-allocation parsing - Uses
Span<T>,stackalloc, andArrayPool - Native Acceleration - Optional C++ native library for even faster processing
- Cross-platform - Windows, Linux, macOS (x64 and ARM64)
- Simple Format - Human-readable key-value format
dotnet add package FONdotnet add package FON
dotnet add package FastObjectNotation.NativeThe FastObjectNotation.Native package automatically includes native binaries for all supported platforms.
using FON.Core;
using FON.Types;
// Create a collection
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)
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 best method)
await Fon.SerializeToFileAutoAsync(dump, new FileInfo("data.fon"));
// Deserialize from file
var loaded = await Fon.DeserializeFromFileAutoAsync(new FileInfo("data.fon"));
// Access data
foreach (var (key, record) in loaded.FonObjects) {
var id = record.Get<int>("id");
Console.WriteLine($"Record {key}: id={id}");
}| 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:"base64..." |
FonCollection |
o |
user=o:{id=i:1,name=s:"Bob"} |
All primitive and string types support arrays (values=i:[1,2,3,4,5]). Nested objects also support arrays of objects (items=o:[{id=i:1},{id=i:2}]).
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).
# Simple values
name=s:"John",age=i:30,balance=d:1234.56
# Arrays
scores=i:[95,87,92,88],tags=s:["admin","user"]
# Binary data (base64 encoded)
image=r:"iVBORw0KGgoAAAANSUhEUg..."
# 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:[]
// Serialize collection to string
string text = Fon.SerializeToString(collection);
// Auto-select best method based on data size (recommended)
await Fon.SerializeToFileAutoAsync(dump, file);
// Pipeline method - best for small datasets (<2000 records)
await Fon.SerializeToFilePipelineAsync(dump, file);
// Chunked method - best for large datasets, lower memory pressure
await Fon.SerializeToFileChunkedAsync(dump, file, chunkSize: 1000);
// Basic parallel serialization
await Fon.SerializeToFileAsync(dump, file);// Auto-select best method based on file size (recommended)
var dump = await Fon.DeserializeFromFileAutoAsync(file);
// Load entire file, parse in parallel - best for files <500MB
var dump = await Fon.DeserializeFromFileAsync(file);
// Stream file in chunks - best for very large files
var dump = await Fon.DeserializeFromFileChunkedAsync(file, chunkSize: 10000);// Automatically decompress RawData during deserialization
Fon.DeserializeRawUnpack = true;
// Adjust threshold for auto method selection (default: 2000)
Fon.ParallelMethodThreshold = 2000;
// Maximum bracket nesting depth (default: 64)
Fon.MaxDepth = 64;FON includes optional native acceleration via a C++ library for maximum performance.
| Package | Description |
|---|---|
FON |
Core library (managed, works everywhere) |
FastObjectNotation.Native |
Meta-package that includes all native binaries |
FastObjectNotation.Native.Runtime |
P/Invoke bindings (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 |
using FON.Acceleration;
if (FonAccelerator.IsAvailable) {
Console.WriteLine($"Native acceleration enabled, version: {FonAccelerator.Version}");
} else {
Console.WriteLine("Using managed implementation");
}| Scenario | Recommendation |
|---|---|
| Small datasets (<1000 records) | Managed is sufficient |
| Large datasets (>10000 records) | Native recommended |
| Memory-constrained environments | Native (lower allocations) |
| Docker/Alpine containers | Use linux-musl-* packages |
| Cross-platform deployment | Install FastObjectNotation.Native for all platforms |
| Single platform deployment | Install specific FastObjectNotation.Native.{rid} package |
If you only need native support for specific platforms (smaller deployment):
# Windows x64 only
dotnet add package FastObjectNotation.Native.Runtime
dotnet add package FastObjectNotation.Native.win-x64
# Linux x64 only
dotnet add package FastObjectNotation.Native.Runtime
dotnet add package FastObjectNotation.Native.linux-x64
# Multiple specific platforms
dotnet add package FastObjectNotation.Native.Runtime
dotnet add package FastObjectNotation.Native.win-x64
dotnet add package FastObjectNotation.Native.linux-x64-
Use Auto methods -
SerializeToFileAutoAsyncandDeserializeFromFileAutoAsyncautomatically select the best strategy -
Adjust parallelism - Pass
maxDegreeOfParallelismparameter to control CPU usage:await Fon.SerializeToFileAutoAsync(dump, file, maxDegreeOfParallelism: 4);
-
Reuse FonDump - Clear and reuse instead of creating new instances
-
Use RawData for binary - More efficient than base64 strings for large binary data
git clone https://github.com/FastObjectNotation/FON.net.git
cd FON.net
# Build managed library
dotnet build
# Build native library (requires CMake)
cmake -B build -S FON.Native -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release
# Run tests
dotnet test