Native Serialization
Native serialization uses an implementation-specific wire format and the host language's native type system. Choose it when every writer and reader uses the same Fory implementation family and the payload should preserve language-specific types or behavior. Native payloads from different implementation families are not interchangeable.
Use xlang serialization whenever a peer with a different native wire format must read the bytes. Xlang uses a shared type system and wire format; native mode deliberately stays closer to the implementation family's native object model.
Native and xlang type support overlap. A type listed on this page is not necessarily exclusive to native mode; many language-native carriers also work in xlang when they have a portable mapping. Choose the mode from the data boundary and required wire contract first, then check the language's type mapping for the specific model.
When To Use Native Mode
Native mode is the right choice when:
- every producer and consumer uses one Fory implementation family;
- the object graph contains language-specific types or behavior outside the portable xlang type mapping;
- an application is moving from an existing same-language serializer and should keep its current object model instead of introducing a cross-language schema; or
- stored or transported data stays within one implementation family rather than a contract shared across implementation families.
Use xlang instead when peers use different Fory implementation families, when the contract must remain language-independent, or when portability is more important than the full native object surface.
| Scenario | Recommended mode |
|---|---|
| One implementation family with language-specific types | Native |
| Replacement for an existing same-language object serializer | Native |
| Data exchanged across Fory implementation families | Xlang |
| A long-lived contract intended to remain language-independent | Xlang |
Java
Choose Java native serialization for Java/JVM-only payloads that need a broader Java object surface than the portable xlang mapping. This includes ordinary Java objects, records, enums, primitive and object arrays, common JDK collections and wrappers, interfaces, inheritance, shared references, and circular object graphs.
Java native mode also supports classes that use JDK serialization hooks:
writeObjectandreadObject;writeReplaceandreadResolve;readObjectNoData; andExternalizable.
Fory honors these hooks while writing Fory native bytes; it does not emit Java
ObjectOutputStream bytes. See JDK Custom Serialization for the exact
semantics.
Use Java native mode when replacing Java-only use of Kryo, FST, Hessian, or JDK serialization and the existing Java object model should remain the serialization model.
Python
Choose Python native serialization for Python-only payloads that need Python objects beyond the portable xlang surface. Native mode supports classes, global and local functions, lambdas, closures, instance methods, class methods, static methods, shared references, and circular object graphs.
It also supports Python object construction and state hooks, including:
__getstate__and__setstate__;__getnewargs__and__getnewargs_ex__; and__reduce__and__reduce_ex__.
Use it when replacing Pickle or cloudpickle for a Python-only object graph. It is also an option for replacing a Python-only MessagePack boundary when both endpoints move to Fory and the application wants to serialize Python objects directly. If MessagePack is currently used as a language-neutral exchange format, use xlang instead.
See Functions, Classes, and Methods and Serialization Hooks for the supported Python object shapes and reconstruction behavior.
Rust
Choose Rust native serialization when every endpoint is Rust and the payload
should use the Rust-specific wire format. This choice does not mean common Rust containers,
Rc<T>, Arc<T>, trait objects, or dyn Any are unavailable in xlang. Those carriers can also
participate in xlang when their selected concrete types have portable mappings. Use the
Xlang Type Mapping and the Rust language guide to check the
exact model.
One native-specific shape is a data-carrying, struct-style enum whose variants contain multiple
fields directly. In native mode, a #[derive(ForyUnion)] enum can mix unit variants, tuple variants
with one or more fields, and named variants with one or more fields:
use fory::ForyUnion;
#[derive(ForyUnion)]
enum Command {
#[fory(default)]
Idle,
Move(i32, i32),
Create { id: u128, label: String },
}
An xlang UNION alternative carries at most one declared payload value. Multiple logical fields must be wrapped in an explicitly declared struct for xlang, while Rust native mode can encode the tuple or named fields directly. See Rust Enum Support and External-Type Serialization for local and third-party enum shapes.
C++
Choose C++ native serialization when every endpoint is C++ and the data model
should use the C++-specific wire format. Standard containers, structs and classes,
std::optional, std::variant, tuple-like values, smart pointers, and supported scalar carriers
are not categorically native-only; they can also work in xlang when the corresponding portable
mapping exists.
Choose native mode because the boundary is C++-only or because the particular model needs a C++-specific representation, not merely because it uses a C++ standard-library type. Use Supported Types for the exact native and xlang mappings.
Migrating From Another Serializer
Native mode is a replacement serialization path, not a decoder for another library's wire format. Kryo, FST, Hessian, JDK serialization, Pickle, cloudpickle, and MessagePack bytes do not become Fory native bytes automatically.
Move writers and readers to the corresponding Fory implementation family together. If existing stored data must remain readable during migration, keep the previous decoder at that boundary and reserialize values with Fory as they are migrated. Do not use native mode for a boundary that still has readers using a different native wire format.
Enable Native Mode
| Language | Native-mode configuration |
|---|---|
| Java | Fory.builder().withXlang(false).build() |
| Python | pyfory.Fory(xlang=False) |
| C++ | Fory::builder().xlang(false).build() |
| Rust | Fory::builder().xlang(false).build() |
Language Guides
Each language guide owns its exact supported types, configuration, schema behavior, extension APIs, and diagnostics.