Thanks to visit codestin.com
Credit goes to fory.apache.org

Skip to main content
Version: dev

Type Registration

This page explains how to register types for serialization.

Overview

Apache Fory™ requires explicit type registration for struct types. This design enables:

  • Cross-Language Compatibility: Registered type IDs are used across language boundaries
  • Type Safety: Detects type mismatches at deserialization time
  • Polymorphic Serialization: Enables serialization of polymorphic objects via smart pointers

Registering Structs

Use register_struct<T>(type_id) to register a struct type:

#include "fory/serialization/fory.h"

using namespace fory::serialization;

struct Person {
std::string name;
int32_t age;
};
FORY_STRUCT(Person, name, age);

int main() {
auto fory = Fory::builder().xlang(true).build();

// Register with a unique type ID
fory.register_struct<Person>(100);

Person person{"Alice", 30};
auto bytes = fory.serialize(person).value();
auto decoded = fory.deserialize<Person>(bytes).value();
}

Type ID Guidelines

Type IDs must be:

  1. Unique: Each type must have a unique ID within a Fory instance
  2. Consistent: Same ID must be used across all languages and versions

User-registered type IDs are in a separate namespace from built-in type IDs, so you can start from 0:

// User type IDs can start from 0
fory.register_struct<Address>(0);
fory.register_struct<Person>(1);
fory.register_struct<Order>(2);

Registering Enums

Use register_enum<T>(type_id) to register an enum type. For simple enums with continuous values starting from 0, no macro is needed:

// Simple continuous enum - no FORY_ENUM needed
enum class Color { RED, GREEN, BLUE }; // Values: 0, 1, 2

// Register with register_enum
fory.register_enum<Color>(0);

For enums with non-continuous values, use the FORY_ENUM macro to map values to ordinals:

// Non-continuous enum values - FORY_ENUM required
enum class Priority { LOW = 10, MEDIUM = 50, HIGH = 100 };
FORY_ENUM(Priority, LOW, MEDIUM, HIGH);

// Global namespace enum (prefix with ::)
enum LegacyStatus { UNKNOWN = -1, OK = 0, ERROR = 1 };
FORY_ENUM(::LegacyStatus, UNKNOWN, OK, ERROR);

// Register after FORY_ENUM
fory.register_enum<Priority>(1);
fory.register_enum<LegacyStatus>(2);

When to use FORY_ENUM:

  • Enum values don't start from 0
  • Enum values are not continuous (e.g., 10, 50, 100)
  • You need name-to-value mapping at compile time

Thread-Safe Registration

For ThreadSafeFory, register types before spawning threads:

auto fory = Fory::builder().xlang(true).build_thread_safe();

// Register all types first
fory.register_struct<TypeA>(100);
fory.register_struct<TypeB>(101);

// Now safe to use from multiple threads
std::thread t1([&]() {
auto result = fory.serialize(obj_a);
});
std::thread t2([&]() {
auto result = fory.serialize(obj_b);
});

Cross-Language Registration

For cross-language compatibility, ensure:

  1. Same Type ID: Use identical IDs in all languages
  2. Compatible Types: Use equivalent types across languages

Java

Fory fory = Fory.builder().build();
fory.register(Person.class, 100);
fory.register(Address.class, 101);

Python

import pyfory

fory = pyfory.Fory()
fory.register(Person, 100)
fory.register(Address, 101)

C++

auto fory = Fory::builder().xlang(true).build();
fory.register_struct<Person>(100);
fory.register_struct<Address>(101);

Built-in Type IDs

Built-in types have pre-assigned type IDs and don't need registration:

Type IDType
0NONE
1BOOL
2INT8
3INT16
4INT32
5VAR_INT32
6INT64
7VAR_INT64
8SLI_INT64
9FLOAT16
10FLOAT32
11FLOAT64
12STRING
13LIST
14MAP
15SET
16TIMESTAMP
17DURATION
18LOCAL_DATE
19DECIMAL
20BINARY
21ARRAY
22BOOL_ARRAY
23-28INT_ARRAY variants
29-31FLOAT_ARRAY variants
32STRUCT
33COMPATIBLE_STRUCT
34NAMED_STRUCT
35NAMEDCOMPATIBLE...
36EXT
37NAMED_EXT
63UNKNOWN

Error Handling

Registration errors are checked at serialization/deserialization time:

// Attempting to serialize unregistered type
auto result = fory.serialize(unregistered_obj);
if (!result.ok()) {
// Error: "Type not registered: ..."
std::cerr << result.error().to_string() << std::endl;
}

// Type ID mismatch during deserialization
auto result = fory.deserialize<WrongType>(bytes);
if (!result.ok()) {
// Error: "Type mismatch: expected X, got Y"
std::cerr << result.error().to_string() << std::endl;
}