title: Cross-Language Serialization sidebar_position: 12 id: cross_language license: | Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Apache Fory™ supports seamless data exchange between Java and other languages (Python, Rust, Go, JavaScript, etc.) through the xlang serialization format. This enables multi-language microservices, polyglot data pipelines, and cross-platform data sharing.
To serialize data for consumption by other languages, use Language.XLANG mode:
import org.apache.fory.*; import org.apache.fory.config.*; // Create Fory instance with XLANG mode Fory fory = Fory.builder() .withLanguage(Language.XLANG) .withRefTracking(true) // Enable reference tracking for complex graphs .build();
Types must be registered with consistent IDs or names across all languages. Fory supports two registration methods:
public record Person(String name, int age) {} // Register with numeric ID - faster and more compact fory.register(Person.class, 1); Person person = new Person("Alice", 30); byte[] bytes = fory.serialize(person); // bytes can be deserialized by Python, Rust, Go, etc.
Benefits: Faster serialization, smaller binary size Trade-offs: Requires coordination to avoid ID conflicts across teams/services
public record Person(String name, int age) {} // Register with string name - more flexible fory.register(Person.class, "example.Person"); Person person = new Person("Alice", 30); byte[] bytes = fory.serialize(person); // bytes can be deserialized by Python, Rust, Go, etc.
Benefits: Less prone to conflicts, easier management across teams, no coordination needed Trade-offs: Slightly larger binary size due to string encoding
import org.apache.fory.*; import org.apache.fory.config.*; public record Person(String name, int age) {} public class Example { public static void main(String[] args) { Fory fory = Fory.builder() .withLanguage(Language.XLANG) .withRefTracking(true) .build(); // Register with consistent name fory.register(Person.class, "example.Person"); Person person = new Person("Bob", 25); byte[] bytes = fory.serialize(person); // Send bytes to Python service via network/file/queue } }
import pyfory from dataclasses import dataclass @dataclass class Person: name: str age: pyfory.int32 # Create Fory in xlang mode fory = pyfory.Fory(xlang=True, ref=True) # Register with the SAME name as Java fory.register_type(Person, typename="example.Person") # Deserialize bytes from Java person = fory.deserialize(bytes_from_java) print(f"{person.name}, {person.age}") # Output: Bob, 25
Cross-language mode supports circular and shared references when reference tracking is enabled:
public class Node { public String value; public Node next; public Node parent; } Fory fory = Fory.builder() .withLanguage(Language.XLANG) .withRefTracking(true) // Required for circular references .build(); fory.register(Node.class, "example.Node"); // Create circular reference Node node1 = new Node(); node1.value = "A"; Node node2 = new Node(); node2.value = "B"; node1.next = node2; node2.parent = node1; // Circular reference byte[] bytes = fory.serialize(node1); // Python/Rust/Go can correctly deserialize this with circular references preserved
Not all Java types have equivalents in other languages. When using xlang mode:
int, long, double, String) for maximum compatibilityList, Map, Set) instead of language-specific onesFloat16, BFloat16, Float16List, BFloat16List) for 16-bit float payloadsFloat16[] and BFloat16[] as xlang list carriers; use Float16List and BFloat16List when the wire type must be float16_array or bfloat16_arrayOptional, BigDecimal (unless the target language supports them)public record UserData( String name, // ✅ Compatible int age, // ✅ Compatible List<String> tags, // ✅ Compatible Map<String, Integer> scores // ✅ Compatible ) {}
public record UserData( Optional<String> name, // ❌ Not cross-language compatible BigDecimal balance, // ❌ Limited support EnumSet<Status> statuses // ❌ Java-specific collection ) {}
Cross-language mode has additional overhead compared to Java-only mode:
For best performance:
withRefTracking(false))Language.JAVA) when only Java serialization is neededLanguage.XLANG mode