Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ProwlEngine/Prowl.Echo/llms.txt
Use this file to discover all available pages before exploring further.
SerializationContext is the configuration and state container that travels through the entire serialization or deserialization pipeline for a given operation. It controls how type metadata is embedded via TypeMode, exposes optional hook delegates that let you intercept and replace the default behavior for specific objects, and maintains the reference-tracking dictionaries used when the same object instance appears more than once in an object graph.
TypeMode Enum
TypeMode governs when Serializer embeds type metadata ($type or $t/$v keys) in the serialized output.
Always embed type information on every serialized object, regardless of whether the runtime type matches the declared type. Useful when the consumer of the data cannot know the declared type ahead of time, or when you need every node to be self-describing.
Embed type information only when the value’s runtime type differs from the declared (target) type. This is the default and produces the most compact output while still supporting polymorphism wherever it is actually needed.
Never embed type information. The smallest possible output, but deserialization must be told the exact concrete type — if the type is wrong the result will be incorrect or an exception will be thrown. Suitable for tightly-coupled scenarios where both sides share a fixed schema.
SerializeOverride Delegate
Serializer before any built-in formatter runs, giving you the opportunity to take full control of how a specific object is serialized.
The object that is about to be serialized.
The active serialization context. You may call
Serializer.Serialize recursively within the delegate using this same context.EchoObject to use that as the serialized representation (normal type-wrapping rules still apply around it). Return null to let the serializer proceed with its built-in formatting pipeline.
DeserializeOverride Delegate
Serializer before any built-in formatter runs during deserialization. The return type is a value-tuple that explicitly signals whether the delegate handled the object.
The
EchoObject node that is about to be deserialized. Type metadata has already been extracted — data is the payload, not a type-envelope wrapper.The resolved target type (after any
$type metadata has been applied).The active deserialization context.
- Return
(true, result)to useresultas the deserialized object; the built-in pipeline is skipped entirely. - Return
(false, null)to let the serializer proceed with its built-in formatting pipeline.
SerializationContext Class
Constructor
NullKey instance is pre-registered at id 0 so that null values round-trip correctly without special-casing.
Determines when type metadata is embedded. See the
TypeMode section above.OnSerialize Property
Serializer.Serialize for every non-primitive, non-null object, before the built-in formatter selection runs. Assign it to intercept specific types — for example, to replace a live asset reference with a path identifier instead of serializing the full asset data.
OnDeserialize Property
Serializer.Deserialize for every non-null node, before the built-in formatter selection runs. Assign it to reconstruct objects from external references or apply custom construction logic.
Reference Tracking Fields
objectToId uses ReferenceEqualityComparer.Instance, so identity — not equality — determines whether two references point to the same object.
You rarely need to interact with
objectToId, idToObject, or nextId directly. They are public so that advanced scenarios — such as custom ISerializationFormat implementations that need to participate in reference tracking — can do so.Code Examples
1. Creating a context with TypeMode.None
Use this when both the writing side and the reading side share the same schema and type information in the payload would be wasteful.
2. Using OnSerialize to intercept serialization
A common pattern in game engines is to serialize asset references as lightweight path identifiers rather than embedding the full asset data inline.
3. Using OnDeserialize to intercept deserialization
The matching read-side hook retrieves the live asset from the registry rather than constructing a new one.
4. Reusing a context across multiple objects
When serializing a group of related objects (e.g., an entire scene), pass the same context to everySerialize call so that shared object instances are tracked consistently across the whole batch.