Supported Types
This page lists the Dart types you can use in Fory messages, and flags where you need to be careful for cross-language compatibility.
Built-in Primitive Types
The following Dart types serialize directly without any special handling:
| Dart type | Cross-language notes |
|---|---|
bool | Direct mapping |
int | Serialized as 64-bit by default. Use @ForyField(type: Int8Type/Int16Type/Int32Type/Uint8Type/Uint16Type/Uint32Type) when the peer expects a narrower integer |
double | Maps to 64-bit float. Use Float32 wrapper when the peer expects 32-bit |
String | Direct mapping |
Uint8List | Binary blob |
List, Set, Map | Supported; element types must also be supported |
DateTime | Use Timestamp or LocalDate wrappers for explicit semantics |
Integer Fields
Dart VM/native int can represent signed 64-bit values, while Dart web int
is limited to JavaScript-safe integer precision. If the peer language expects a
32-bit integer (Java int, Go int32, C# int) and you send a Dart int,
the deserialization may fail or silently truncate. For browser and Flutter web
precision rules, see Web Platform Support.
Use field metadata to select the wire type explicitly for 8/16/32-bit fields:
@ForyStruct()
class Metrics {
Metrics();
@ForyField(type: Int8Type())
int tiny = 0;
@ForyField(type: Int32Type(encoding: Encoding.fixed))
int age = 0;
@ForyField(type: Uint32Type())
int count = 0;
Int64 sequence = Int64(0);
Uint64 offset = Uint64(0);
}
Generated serializers range-check annotated int values before writing them.
Use Int64 and Uint64 when you need full-range 64-bit values, especially on
web. A plain root int value serializes as xlang int64; exact 8/16/32-bit
wire widths are selected through field metadata or low-level Buffer APIs.
On Dart VM, Int64 and Uint64 are extension types over int. Once a value is
passed through an Object-typed dynamic/root boundary, the VM cannot recover
whether it was originally a plain int, Int64, or Uint64. Use generated
field metadata or explicit Buffer APIs when native VM payloads must preserve
unsigned 64-bit identity across dynamic boundaries. Dart web uses wrapper
classes, so web root Uint64 values keep varuint64 metadata.
Floating-Point Types
Dart double maps to 64-bit float by default. If the peer uses
reduced-precision floating-point values, keep the Dart field as double and
mark the exact wire type with field metadata:
Float32— 32-bit float (matches Javafloat, C#float, Gofloat32)@ForyField(type: Float16Type()) double value— half-precision scalar@ForyField(type: Bfloat16Type()) double value— bfloat16 scalar
For contiguous 16-bit floating-point arrays, use Float16List and
Bfloat16List rather than Uint16List when the schema is array<float16>
or array<bfloat16>.
Time and Date Types
Avoid sending raw DateTime across languages — time zone handling and epoch differences vary. Use the explicit wrappers instead:
Timestamp— a UTC instant with nanosecond precision (seconds + nanoseconds)LocalDate— a calendar date without time or time zoneDuration— an elapsed time value using Dart's built-inDuration
final now = Timestamp.fromDateTime(DateTime.now().toUtc());
final birthday = LocalDate(1990, 12, 1);
final timeout = const Duration(seconds: 30);
The temporal wrappers expose conversion helpers:
Timestamp.fromDateTime(...)andtimestamp.toDateTime()LocalDate.fromEpochDay(Int64(...)),date.toEpochDay()returnsInt64LocalDate.fromDateTime(...)anddate.toDateTime()
Duration support in Dart is exact to microseconds. Incoming xlang duration
payloads that use sub-microsecond nanoseconds are rejected instead of being
silently truncated.
Structs and Enums
Annotate classes with @ForyStruct() and run build_runner to make them serializable. Enums in the same file are included automatically.
@ForyStruct()
class User {
User();
String name = '';
@ForyField(type: Int32Type())
int age = 0; // use explicit field metadata when peers expect a 32-bit integer
}
See Code Generation.
Collections
Fory supports List<T>, Set<T>, and Map<K, V>. Element and key types must
also be serializable types. Avoid using mutable objects as map keys.
Generic List<int> with primitive element metadata still uses list<T> schema.
Dedicated dense array schema comes from dedicated carriers:
BoolListplus@ArrayField(element: BoolType())forarray<bool>. PlainList<bool>maps tolist<bool>.Int8List,Int16List,Int32List,Int64ListUint8List,Uint16List,Uint32List,Uint64ListFloat16List,Bfloat16List,Float32List,Float64List
Compatibility Tip
When in doubt about whether a Dart type will match what the peer expects, make
the width explicit with @ForyField(type: ...). Guessing the wrong numeric
width is one of the most common cross-language bugs.