Skip to main content
The Prowl.Echo source generator analyzes your types at compile time and emits optimized Serialize and Deserialize methods that implement ISerializable. By inlining primitive construction and bypassing the reflection pipeline entirely, source-generated types are significantly faster than reflection-based serialization — outperforming both System.Text.Json and Newtonsoft.Json across all benchmarks.

Getting Started

Add [GenerateSerializer] to any partial class or struct. The partial keyword is required so the generator can add the generated code alongside your definition.
The generator produces a Serialize and Deserialize method in a separate partial file. You use Serializer.Serialize and Serializer.Deserialize exactly as normal — the generated code is called automatically:
The source generator is bundled in the Prowl.Echo NuGet package under analyzers/dotnet/cs. No separate package or manual reference is needed.

Requirements

partial keyword

The class or struct must be declared partial — the generator adds a second partial declaration with the generated code.

Fields only

Only public fields (and private fields with [SerializeField]) are generated. Properties are never serialized.

What the Generator Inlines

The generator classifies each field into a FieldTypeCategory and emits the most efficient code for its type. Inline handling is used for the following categories — all other types, including Nullable<T>, fall back to Serializer.Serialize/Serializer.Deserialize: For collection types (List<T>, T[], Dictionary<string, T>), the element type must itself be a simple known category (primitive, string, enum, or Guid). Nested collections or complex element types fall back to Serializer.Serialize.

Using Attributes with Generated Code

All serialization attributes work with [GenerateSerializer]:
The generated Serialize method wraps conditional fields in the appropriate if guards. [FormerlySerializedAs] generates additional else if (value.TryGet("hp", out var ...)) branches in the Deserialize method.

Performance Comparison

With [GenerateSerializer] and [FixedEchoStructure] on a complex object graph (20 nested objects, 100-element arrays, 50-entry dictionaries, collections):
For maximum performance combine [GenerateSerializer] with [FixedEchoStructure] on small, stable value types like vectors and network packets. See Fixed Structure for details.

vs. Manual ISerializable

[GenerateSerializer] auto-generates ISerializable for you. You only need to implement it manually when you need logic the generator cannot express — for example, computing a derived field or migrating data between schema versions. See Custom Serialization for the manual approach.