跳到主要内容
版本:1.5.0

Xlang 序列化

Fory Swift 可以通过 xlang 协议与其他 Fory 实现交换载荷。

推荐的 Xlang 配置

let fory = Fory()

用共享身份注册类型

基于 ID 的注册

@ForyStruct
struct Order {
var id: Int64 = 0
var amount: Double = 0
}

let fory = Fory()
try fory.register(Order.self, id: 100)

基于名称的注册

try fory.register(Order.self, name: "com.example.Order")

Xlang 规则

  • 在不同语言之间保持一致的类型注册映射
  • 当各端 Schema 独立演进时,保持启用兼容模式。Swift 默认启用该模式
  • 注册动态字段和应用协议值使用的所有用户定义具体目标类型
  • 对于由其他模块拥有的类型,使用外部结构化序列化器、单独定义的自定义序列化器,或有意添加的 目标为自身的追溯遵循

List 与密集数组

除非字段元数据显式要求使用密集的 array<T>,否则 Swift Array<T> 字段会映射为 Fory list<T>array<T> 仅用于一维 bool 或数值数据。

Fory SchemaSwift 字段元数据示例
list<int32>@ListField(element: .int32()) var ids: [Int32]
array<bool>@ArrayField(element: .bool) var flags: [Bool]
array<int8>@ArrayField(element: .int8) var values: [Int8]
array<int16>@ArrayField(element: .int16) var values: [Int16]
array<int32>@ArrayField(element: .int32()) var values: [Int32]
array<int64>@ArrayField(element: .int64()) var values: [Int64]
array<uint8>@ArrayField(element: .uint8) var values: [UInt8]
array<uint16>@ArrayField(element: .uint16) var values: [UInt16]
array<uint32>@ArrayField(element: .uint32()) var values: [UInt32]
array<uint64>@ArrayField(element: .uint64()) var values: [UInt64]
array<float16>@ArrayField(element: .float16) var values: [Float16]
array<bfloat16>@ArrayField(element: .bfloat16) var values: [BFloat16]
array<float32>@ArrayField(element: .float32) var values: [Float]
array<float64>@ArrayField(element: .float64) var values: [Double]

使用单独元素序列化器的数组仍采用普通的 list 编码。@ArrayField 仅用于受支持的密集 bool 或 数值数组。

外部目标类型

外部结构化序列化器生成的 xlang STRUCT、ENUM 或 UNION Schema 及值字节,与等效的普通 Swift 模型相同:

@ForyStruct(target: ThirdParty.Order.self)
struct OrderSerializer {
var id: Int64
var amount: Double
}

try fory.register(OrderSerializer.self, id: 100)

在字段元数据中使用 .with(...),在根值上使用 with:。详见 外部类型序列化

由于结构化序列化器是单独的声明,因此必须显式选择它。如果外部类型有一个有意添加且 Target == Self 的追溯遵循,则会改用常规的根值、字段和容器。

Swift 不提供原生序列化模式。一个已知的 @ForyUnion case 包含零个或一个关联值。如果一个联合 类型备选项包含多个逻辑字段,请使用结构体载荷。

Swift IDL 工作流

可直接从 Fory IDL、Proto 或 FBS 输入生成 Swift 模型:

foryc schema.fdl --swift_out ./Sources/Generated

生成的 Swift 代码包括:

  • @ForyStruct@ForyEnum@ForyUnion 以及字段和 case 元数据
  • 带 tag 的联合类型枚举(带关联值的枚举 case)
  • 支持传递式安装导入模块的 ForyModule.install(_:) 辅助方法
  • 生成类型上的 toBytes / fromBytes 帮助方法

在 xlang 序列化之前,请先安装生成的模块:

let fory = Fory(ref: true)
try Addressbook.ForyModule.install(fory)

let payload = try fory.serialize(book)
let decoded: Addressbook.AddressBook = try fory.deserialize(payload)

运行 Swift IDL 集成测试

cd integration_tests/idl_tests
./run_swift_tests.sh

这会执行 Swift roundtrip 矩阵测试以及 Java 对端 roundtrip 检查(IDL_PEER_LANG=swift)。

调试 Xlang 测试

运行 xlang 测试时可以开启调试输出:

ENABLE_FORY_DEBUG_OUTPUT=1 FORY_SWIFT_JAVA_CI=1 mvn -T16 test -Dtest=org.apache.fory.xlang.SwiftXlangTest