Repository navigation
v1.0.0 — Stable wire format 🎉
Serde.FS leaves beta. The JSON wire format is now a documented contract: every shape the .NET codecs and the Fable client write is listed in the README, and 1.x will read what any 1.x wrote. Any change that would break that waits for 2.0.
⚠️ Upgrading from beta
- Upgrade all Serde.FS packages together, and redeploy client and server as a unit. A few wire shapes changed (below), so a beta client and a 1.0 server can disagree. A browser tab still running the old client can hit errors until it reloads.
- JSON you stored with beta.6 should still decode. The decoders still accept the old shapes where the format changed (
int64/decimalas numbers,nullfor a nested option). - Removed attributes:
[<SerdeSerialize>],[<SerdeDeserialize>],[<SerdeSkipSerialize>]and[<SerdeSkipDeserialize>]. They were read by the generator and then ignored, so no generated code changes: replace the first two with[<Serde>]and delete the skip attributes.[<SerdeSkip>]on a record field is now a build error (it never skipped anything); it still works on union cases and enum cases.
Wire format changes
int64,uint64anddecimalare JSON strings ("9223372036854775807"). JavaScript reads JSON numbers as doubles, so the Fable client silently lost precision past 2^53. A JSON number is still accepted on decode.Some Nonesurvives. For a nested option orunit option,Someis written as{"Some": ...};Some Noneused to collapse toNone. Single options are unchanged:Some 5is5,Noneisnull.- Null
byte[], arrays and seqs from interop are written asnullinstead of throwing, andSome nullis sent asNone, the same rule as strings. - New codecs:
sbyte,int16,byte,uint16,uint32,uint64,float32,charandTimeSpan(.NET constant format,"1.02:03:04.5000000"). Fields of these types used to fail at runtime.
Stricter decoding
The rule for 1.0: when in doubt, reject. A decoder can be loosened later without breaking anyone; tightening it would break.
- Integers reject fractional (
1.9) and out-of-range values instead of truncating or wrapping them.NaNand infinity are rejected. - Dates and times decode from ISO 8601 only. Culture-shaped text like
"01/02/2026"is no longer accepted. Guiddecodes only the standard hyphenated form.- A union's
Fieldsand a tuple must hold exactly as many values as the type has; extra values used to be ignored.
Clearer decode errors
.NET and the Fable client now fail with the same messages, naming the type and field:
Missing field "Zip" for Shop.Address
Union case Shop.Shape.Rectangle expects 2 field(s), got 1
Unknown case "Hexagon" for Shop.Shape
Expected a JSON object for Shop.Address, got an array
These replace a bare KeyNotFoundException / IndexOutOfRangeException on .NET, and on Fable an undefined value that surfaced later.
Fixes
- Culture independence: numbers were written with the current culture (
1,5under de-DE) and dates parsed with it. Both now use the invariant culture. floatprecision: floats were encoded throughdecimal, which keeps 15 significant digits and fails outside its range. They are now written in the shortest form that round-trips.- Fable client dates:
DateTimekind andDateTimeOffsetoffset are preserved; a UTC value no longer shifts by the browser's offset when sent back. - Fable client
float32is rounded to single precision on decode. - Qualified primitives (
System.Guid,System.TimeSpan) in an option or tuple no longer break the build. - Named RPC parameters (
abstract Probe: from: DateTime * until: DateTime -> ...) no longer generateobj(#16). - Fable generator on Linux: backslash
ProjectReferencepaths and paths containing uppercase letters work on case-sensitive file systems (#17).
Tested in both directions
- A new round-trip suite sends the same values through the .NET codecs and through the generated Fable client under Node. Each side decodes what the other wrote. It covers:
- every number type at its limits;
- unicode and escapes;
- all date and time types;
- nested options, collections,
Maps with non-string keys, unions, renames and bare RPC values.
- A Linux CI job runs the tests, the sample apps, the round-trip suite and the Native AOT / trimming gate on every push.
Full changelog: v1.0.0-beta.6...v1.0.0