CodecMapper 0.2.0
Prefix ReservedSee the version list below for details.
dotnet add package CodecMapper --version 0.2.0
NuGet\Install-Package CodecMapper -Version 0.2.0
<PackageReference Include="CodecMapper" Version="0.2.0" />
<PackageVersion Include="CodecMapper" Version="0.2.0" />
<PackageReference Include="CodecMapper" />
paket add CodecMapper --version 0.2.0
#r "nuget: CodecMapper, 0.2.0"
#:package CodecMapper@0.2.0
#addin nuget:?package=CodecMapper&version=0.2.0
#tool nuget:?package=CodecMapper&version=0.2.0
CodecMapper
CodecMapper is a schema-first serialization library for F# with native AOT and Fable compatibility.
It lets you define one schema and compile it into multiple codecs. The same mapping drives both encode and decode, so JSON and XML stay symmetric.
It's for cases where the wire contract should be explicit, reviewable, and reusable instead of being inferred from CLR shape or serializer settings.
The idea
You author one Schema<'T> that describes the wire shape:
open CodecMapper
open CodecMapper.Schema
type Person = { Id: int; Name: string }
let makePerson id name = { Id = id; Name = name }
let personSchema =
define<Person>
|> construct makePerson
|> field "id" _.Id
|> field "name" _.Name
|> build
Then you compile that schema into a reusable codec:
let codec = Json.compile personSchema
let person = { Id = 1; Name = "Ada" }
let json = Json.serialize codec person
let decoded = Json.deserialize codec json
That is the core model of the library:
- the schema is the contract
- encode and decode come from the same definition
- contract changes stay visible in one place
Why use it
CodecMapper fits when:
- you want the wire contract to be authored explicitly
- JSON and XML should stay symmetric
- domain refinement should be explicit with
Schema.maporSchema.tryMap - Native AOT and Fable compatibility matter
It is not trying to replace convention-based serializers for every use case.
Formats and scope
The same authored schema can compile into:
- JSON codecs
- XML codecs
- config-oriented YAML codecs
- flat KeyValue projections
The core library stays focused on explicit schemas and handwritten runtimes. The separate bridge assembly exists for .NET interoperability with existing C# serializer contracts.
Start here
- Introduction
- Getting Started
- How To Model A Basic Record
- How To Model A Nested Record
- How To Model A Validated Wrapper
Use these after the core authored path is clear:
- How To Import Existing C# Contracts
- How To Export JSON Schema
- JSON Schema in CodecMapper
- API Reference
Compatibility
CodecMapper is designed to stay usable from Native AOT and Fable-oriented targets. CI includes both in-repo compatibility sentinels and packaged-consumer Fable checks.
Performance Status
Current status is mixed but clear:
CodecMapperis competitive on small messages and medium nested-record workloads.System.Text.Jsonstill leads on string-heavy and numeric-heavy payloads.Newtonsoft.Jsontrails both across the current manual scenario matrix.
The project ships both a manual scenario runner and a repeatable perf workflow for hot-path investigation:
- manual runner:
dotnet run -c Release --project benchmarks/CodecMapper.Benchmarks.Runner/CodecMapper.Benchmarks.Runner.fsproj - profiling guide: docs/HOW_TO_PROFILE_BENCHMARK_HOT_PATHS.md
- full benchmark page: docs/BENCHMARKS.md
Latest local manual snapshot, measured on March 11, 2026:
| Scenario | CodecMapper serialize | STJ serialize | CodecMapper deserialize | STJ deserialize | Takeaway |
|---|---|---|---|---|---|
small-message |
3.0 us |
3.6 us |
6.9 us |
5.2 us |
CodecMapper wins serialize on tiny payloads; STJ still leads deserialize. |
person-batch-25 |
76.1 us |
68.5 us |
152.2 us |
152.5 us |
Medium nested decode is effectively even; serialize remains close. |
person-batch-250 |
436.0 us |
386.9 us |
1.303 ms |
1.074 ms |
Larger nested batches are still competitive, but STJ leads on throughput. |
escaped-articles-20 |
236.4 us |
192.9 us |
410.7 us |
325.8 us |
String-heavy payloads are a clear weak spot today. |
telemetry-500 |
1.984 ms |
1.609 ms |
3.981 ms |
2.810 ms |
Numeric-heavy flat payloads still need real optimization work. |
person-batch-25-unknown-fields |
40.4 us |
39.3 us |
158.9 us |
129.4 us |
Unknown-field decode improved, but STJ still holds a noticeable lead. |
Those numbers are machine-specific. Compare ratios and workload shape more than the absolute values.
| 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
- FSharp.Core (>= 10.0.103)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Added file-split core source layout, compile aliases and validated schema helpers, path-aware decode diagnostics, common contract-pattern docs, property-based codec law coverage, and repeatable benchmark hot-path profiling.