Skip to main content
Version: dev

Custom Serializers

Use custom serializers when a type is not generated with [ForyObject] or requires specialized encoding.

Implement Serializer<T>

using Apache.Fory;

public sealed class Point
{
public int X { get; set; }
public int Y { get; set; }
}

public sealed class PointSerializer : Serializer<Point>
{
public override Point DefaultValue => new();

public override void WriteData(WriteContext context, in Point value, bool hasGenerics)
{
context.Writer.WriteVarInt32(value.X);
context.Writer.WriteVarInt32(value.Y);
}

public override Point ReadData(ReadContext context)
{
return new Point
{
X = context.Reader.ReadVarInt32(),
Y = context.Reader.ReadVarInt32(),
};
}
}

Register the Serializer

Fory fory = Fory.Builder().Build();
fory.Register<Point, PointSerializer>(200);

Point value = new() { X = 10, Y = 20 };
byte[] payload = fory.Serialize(value);
Point decoded = fory.Deserialize<Point>(payload);

Serializer Behavior Notes

  • WriteData / ReadData only handle payload content.
  • Ref flags and type info are handled by base Serializer<T>.Write / Read unless overridden.
  • DefaultValue is used for null/default fallback paths.

Best Practices

  1. Keep serializers deterministic and symmetric.
  2. Use varint/fixed/tagged encoding intentionally for integer-heavy payloads.
  3. Register custom serializers on all reader/writer peers.
  4. Prefer generated [ForyObject] serializers for normal domain models.