Overview
Fory Definition Language (FDL) is a schema definition language for Apache Fory that enables type-safe cross-language serialization. Define your data structures once and generate native data structure code for Java, Python, Go, Rust, and C++.
Overview
FDL provides a simple, intuitive syntax for defining cross-language data structures:
package example;
enum Status [id=100] {
PENDING = 0;
ACTIVE = 1;
COMPLETED = 2;
}
message User [id=101] {
string name = 1;
int32 age = 2;
optional string email = 3;
repeated string tags = 4;
}
message Order [id=102] {
ref User customer = 1;
repeated Item items = 2;
Status status = 3;
map<string, int32> metadata = 4;
}
Why FDL?
Schema-First Development
Define your data model once in FDL and generate consistent, type-safe code across all languages. This ensures:
- Type Safety: Catch type errors at compile time, not runtime
- Consistency: All languages use the same field names, types, and structures
- Documentation: Schema serves as living documentation
- Evolution: Managed schema changes across all implementations
Fory-Native Features
Unlike generic IDLs, FDL is designed specifically for Fory serialization:
- Reference Tracking: First-class support for shared and circular references via
ref - Nullable Fields: Explicit
optionalmodifier for nullable types - Type Registration: Built-in support for both numeric IDs and namespace-based registration
- Native Code Generation: Generates idiomatic code with Fory annotations/macros
Zero Runtime Overhead
Generated code uses native language constructs:
- Java: Plain POJOs with
@ForyFieldannotations - Python: Dataclasses with type hints
- Go: Structs with struct tags
- Rust: Structs with
#[derive(ForyObject)] - C++: Structs with
FORY_STRUCTmacros
Quick Start
1. Install the Compiler
cd compiler
pip install -e .
2. Write Your Schema
Create example.fdl:
package example;
message Person [id=100] {
string name = 1;
int32 age = 2;
optional string email = 3;
}
3. Generate Code
# Generate for all languages
foryc example.fdl --output ./generated
# Generate for specific languages
foryc example.fdl --lang java,python --output ./generated
4. Use Generated Code
Java:
Fory fory = Fory.builder().withLanguage(Language.XLANG).build();
ExampleForyRegistration.register(fory);
Person person = new Person();
person.setName("Alice");
person.setAge(30);
byte[] data = fory.serialize(person);
Python:
import pyfory
from example import Person, register_example_types
fory = pyfory.Fory()
register_example_types(fory)
person = Person(name="Alice", age=30)
data = fory.serialize(person)
Documentation
| Document | Description |
|---|---|
| FDL Syntax Reference | Complete language syntax and grammar |
| Type System | Primitive types, collections, and type rules |
| Compiler Guide | CLI options and build integration |
| Generated Code | Output format for each target language |
| Protocol Buffers IDL Support | Comparison with protobuf and migration guide |
| FlatBuffers IDL Support | FlatBuffers mapping rules and codegen differences |
Key Concepts
Type Registration
FDL supports two registration modes:
Numeric Type IDs - Fast and compact:
message User [id=100] { ... } // Registered with ID 100
Namespace-based - Flexible and readable:
message Config { ... } // Registered as "package.Config"
Field Modifiers
optional: Field can be null/Noneref: Enable reference tracking for shared/circular referencesrepeated: Field is a list/array
message Example {
optional string nullable = 1;
ref Node parent = 2;
repeated int32 numbers = 3;
}
Cross-Language Compatibility
FDL types map to native types in each language:
| FDL Type | Java | Python | Go | Rust | C++ |
|---|---|---|---|---|---|
int32 | int | int | int32 | i32 | int32_t |
string | String | str | string | String | std::string |
bool | boolean | bool | bool | bool | bool |
See Type System for complete mappings.
Best Practices
- Use meaningful package names: Group related types together
- Assign type IDs for performance: Numeric IDs are faster than name-based registration
- Reserve ID ranges: Leave gaps for future additions (e.g., 100-199 for users, 200-299 for orders)
- Use
optionalexplicitly: Make nullability clear in the schema - Use
reffor shared objects: Enable reference tracking when objects are shared
Examples
See the examples directory for complete working examples.