title: Cross-Language Serialization sidebar_position: 80 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
Fory JavaScript serializes to the same binary format as the Java, Python, Go, Rust, Swift, and C++ Fory runtimes. You can write a message in JavaScript and read it in Java — or any other direction — without any conversion layer.
Things to keep in mind:
For a message to survive a round trip between JavaScript and another runtime:
namespace + typeName.Type.int32() field in JavaScript matches Java int, Go int32, C# int.compatible mode if using schema evolution.compatible settings.JavaScript side:
import Fory, { Type } from "@apache-fory/core"; const messageType = Type.struct( { typeName: "example.message" }, { id: Type.int64(), content: Type.string(), }, ); const fory = new Fory(); const { serialize } = fory.register(messageType); const bytes = serialize({ id: 1n, content: "hello from JavaScript", });
On the other side, register the same example.message type (same name or same numeric ID) using the peer runtime's API:
Fory matches fields by name. When models are defined in multiple languages, keep field names consistent — or at minimum use a naming scheme that maps unambiguously across languages (e.g. snake_case everywhere).
When using compatible: true for schema evolution, field order differences are tolerated, but the names themselves must still match.
JavaScript number is a 64-bit float, which does not map cleanly to every integer type in other languages. Use explicit schema types:
Type.int32() for 32-bit integers (Java int, Go int32, C# int)Type.int64() with bigint values for 64-bit integers (Java long, Go int64)Type.float32() or Type.float64() for floating-point valuesType.timestamp() — a point in time; round-trips as a JavaScript DateType.date() — a date without time; deserializes as DateType.duration() — exposed as a numeric millisecond value in JavaScriptType.any() lets a field hold different types at runtime, but it is harder to keep in sync across languages. Prefer explicit field schemas whenever possible.
const wrapperType = Type.struct( { typeId: 3001 }, { payload: Type.any(), }, );
Enum member order must match across languages. Fory encodes enums by ordinal position, not by value.
const Color = { Red: 1, Green: 2, Blue: 3 }; const fory = new Fory(); fory.register(Type.enum({ typeId: 210 }, Color));
Use the same type ID or type name in every peer runtime.
The maxDepth, maxBinarySize, and maxCollectionSize options protect the JavaScript runtime from overly large payloads. They do not change the binary format — they only control what the local runtime is willing to accept.