RPC Serialization Formats
ActualLab.Rpc supports multiple serialization formats with automatic version negotiation between clients and servers. This enables gradual upgrades and interoperability between different Fusion versions.
Overview
RPC serialization has two layers:
- Argument serialization: How method arguments are encoded
- Message serialization: How RPC messages (containing arguments) are framed
Each combination of these is packaged as an RpcSerializationFormat.
Available Formats
Text Formats (JSON)
| Format | Key | Description |
|---|---|---|
SystemJsonV3 | json3 | System.Text.Json with V3 argument/message serialization |
SystemJsonV5 | json5 | System.Text.Json with V4 arguments, V3 messages |
NewtonsoftJsonV3 | njson3 | Newtonsoft.Json with V3 argument/message serialization |
NewtonsoftJsonV5 | njson5 | Newtonsoft.Json with V4 arguments, V3 messages |
Binary Formats (MemoryPack)
| Format | Key | Description |
|---|---|---|
MemoryPackV1 | mempack1 | Legacy V1 format |
MemoryPackV2 | mempack2 | V2 args with forced polymorphism |
MemoryPackV2C | mempack2c | Compact variant of V2 |
MemoryPackV3 | mempack3 | V3 arguments |
MemoryPackV3C | mempack3c | Compact variant of V3 |
MemoryPackV4 | mempack4 | V3 args, V4 messages |
MemoryPackV4C | mempack4c | Compact variant of V4 |
MemoryPackV5 | mempack5 | V4 args, V4 messages |
MemoryPackV5C | mempack5c | Compact variant of V5 |
Binary Formats (MessagePack)
| Format | Key | Description |
|---|---|---|
MessagePackV1 | msgpack1 | Legacy V1 format |
MessagePackV2 | msgpack2 | V2 args with forced polymorphism |
MessagePackV2C | msgpack2c | Compact variant of V2 |
MessagePackV3 | msgpack3 | V3 arguments |
MessagePackV3C | msgpack3c | Compact variant of V3 |
MessagePackV4 | msgpack4 | V3 args, V4 messages |
MessagePackV4C | msgpack4c | Compact variant of V4 |
MessagePackV5 | msgpack5 | V4 args, V4 messages |
MessagePackV5C | msgpack5c | Compact variant of V5 |
Non-Polymorphic Variants
Some formats have -np (non-polymorphic) variants that skip type decoration:
| Format | Key |
|---|---|
MemoryPackV2NP | mempack2-np |
MemoryPackV2CNP | mempack2c-np |
MessagePackV2NP | msgpack2-np |
MessagePackV2CNP | msgpack2c-np |
Format Selection
Default Format
The default format is typically MemoryPackV5C (or latest version) for .NET 6+ and MessagePackV5C for .NET Standard.
Client-Server Negotiation
When a client connects, it sends its supported formats. The server selects the best matching format:
Accessing All Formats
// All registered formats
ImmutableList<RpcSerializationFormat> all = RpcSerializationFormat.All;
// Find by key
var format = RpcSerializationFormat.All.First(f => f.Key == "mempack5c");Format Structure
Each RpcSerializationFormat consists of:
public sealed class RpcSerializationFormatExample(
string key,
Func<RpcArgumentSerializer> argumentSerializerFactory,
Func<RpcPeer, IByteSerializer<RpcMessage>> messageSerializerFactory)
{
public string Key { get; } = key;
public RpcArgumentSerializer ArgumentSerializer { get; } = argumentSerializerFactory();
public Func<RpcPeer, IByteSerializer<RpcMessage>> MessageSerializerFactory { get; } = messageSerializerFactory;
}| Property | Description |
|---|---|
Key | Unique string identifier for negotiation |
ArgumentSerializer | Serializes method arguments |
MessageSerializerFactory | Creates message serializers per peer |
Version Differences
Argument Serializer Versions
| Version | Description |
|---|---|
| V1 | Original format, forced polymorphism |
| V2 | Improved with optional polymorphism |
| V3 | Optimized encoding |
| V4 | Latest, best performance |
Message Serializer Versions
| Version | Variants | Description |
|---|---|---|
| V3 | Normal, Compact | Standard message framing |
| V4 | Normal, Compact | Improved framing |
Compact vs Normal
Compact variants (*C suffix) use smaller message framing at a slight CPU cost. Choose compact for:
- Lower bandwidth scenarios
- When message overhead is significant relative to payload
Configuring Formats
Registering Additional Formats
RpcSerializationFormat.All = RpcSerializationFormat.All.Add(
new RpcSerializationFormat(
"custom",
() => new MyArgumentSerializer(),
peer => new MyMessageSerializer(peer)));Removing Formats
To disable older formats for security:
// To disable older formats for security:
RpcSerializationFormat.All = RpcSerializationFormat.All
.RemoveAll(f => f.Key.StartsWith("mempack1") || f.Key.StartsWith("msgpack1"));Format Selection Factors
When choosing formats, consider:
| Factor | Recommendation |
|---|---|
| Performance | Binary formats (MemoryPack > MessagePack > JSON) |
| Debugging | JSON formats (human-readable) |
| Compatibility | MessagePack for .NET Standard clients |
| Bandwidth | Compact variants (*C) |
| Security | Latest versions, disable V1 |
Serialization in RPC Pipeline
- Client serializes method arguments using
ArgumentSerializer - Arguments are wrapped in an
RpcMessageand serialized byMessageSerializer - Binary data is sent over WebSocket
- Server deserializes in reverse order
Related Topics
- Core Serialization - General serialization infrastructure
- RPC Key Concepts - RPC architecture overview
- Configuration Options - RPC configuration
