Skip to main content
Version: dev

Type Registration

Fory needs to know which class corresponds to which type in a serialized message. You do this by registering each class before you serialize or deserialize it.

Choosing a Registration Strategy

Fory offers two strategies. Pick one and use it consistently across every language that reads or writes the type.

Strategy 1: Numeric ID

Compact and fast. Good when a small team can coordinate IDs across services.

ModelsForyModule.register(fory, User, id: 100);

The same number must be used in every other language:

// Java side
fory.register(User.class, 100);

Strategy 2: Name

More self-describing. Good when multiple teams or packages define types independently and numeric ID coordination is impractical.

ModelsForyModule.register(
fory,
User,
name: 'example.User',
);

Every peer that reads or writes this type must use the same name. Use . inside name to add a namespace prefix.

Do not mix strategies for the same type. If one side uses a numeric ID and the other uses a name, deserialization will fail.

Registering Generated Types

Call the generated register function from the .fory.dart file. It installs all the serializer metadata for you:

UserModelsForyModule.register(fory, User, id: 100);

For an ordinary inherited type, register the concrete annotated child. Its generated serializer already owns the complete flattened child schema; Fory does not require separate registration of a superclass or mixin merely because it contributes fields.

Register an independently annotated concrete parent only when values whose actual type is exactly that parent are also serialized. A provider-only @ForyStruct(exposePrivateFields: true) boundary supplies generated field access and has no registration entry of its own. See Struct Inheritance for boundary and child-schema options.

External structural serializers use the same generated registration API. Pass the external target type:

ExternalSerializersForyModule.register(
fory,
third_party.User,
id: 100,
);

See External-Type Serialization for the declaration.

Registering a Custom Serializer

Pass a serializer instance directly when a type needs custom wire or construction logic:

fory.registerSerializer(
ExternalType,
const ExternalTypeSerializer(),
name: 'example.ExternalType',
);

See Custom Serializers for how to implement a serializer.

Rules to Follow

  • Register before the first serialize, serializeTo, serializeBuiltin, serializeBuiltinTo, deserialize, or deserializeFrom call. That first root operation permanently closes registration for the Fory instance, even if the operation fails; create a new instance when a different registry is required.
  • Register every class that can appear in a message, not only the root type.
  • Do not register generated private-field access companions; register only concrete serialized types.
  • Keep IDs (or names) stable once payloads are persisted or exchanged across services. Changing them will break deserialization of old messages.
  • Do not mix a numeric ID on one side with a name on the other for the same type.

Xlang Requirements

The same numeric ID or name must be used in every peer that reads or writes the type. See Cross-Language Interoperability for examples.