类型注册
类型注册用于告知 Fory 如何识别并序列化你的自定义类型。对于结构体、枚举和扩展类型,注册是必需的。
为什么要注册类型?
- 类型识别:反序列化时,Fory 需要知道实际类型
- 多态支持:反 序列化接口类型时,Fory 需要知道要创建哪个具体类型
- 跨语言兼容:其他语言实现需要识别并反序列化你的类型
结构体注册
通过 ID 注册
使用数值类型 ID 注册结构体,可获得更紧凑的序列化结果:
type User struct {
ID int64
Name string
}
f := fory.New()
err := f.RegisterStruct(User{}, 1)
if err != nil {
panic(err)
}
ID 使用建议:
- ID 在应用内必须唯一
- 若用于跨语言,所有语言中的 ID 必须一致
- 序列化端和反序列化端必须为同一类型使用同一 ID
通过名称注册
使用类型名字符串注册结构体。该方式更灵活,但序列化开销更高:
f := fory.New()
err := f.RegisterNamedStruct(User{}, "example.User")
if err != nil {
panic(err)
}
名称使用建议:
- 使用
namespace.TypeName约定的全限定名 - 名称在所有语言中必须唯一且一致
- 名称区分大小写
枚举注册
Go 没有原生枚举类型,但可以把整数类型按枚举注册。
通过 ID 注册
type Status int32
const (
StatusPending Status = 0
StatusActive Status = 1
StatusComplete Status = 2
)
f := fory.New()
err := f.RegisterEnum(Status(0), 1)
通过名称注册
err := f.RegisterNamedEnum(Status(0), "example.Status")
扩展类型
对于需要自定义序列化逻辑的类型,可将其注册为扩展类型,并提供自定义序列化器:
f := fory.New()
// Register by ID
err := f.RegisterExtension(CustomType{}, 1, &CustomSerializer{})
// Or register by name
err = f.RegisterNamedExtension(CustomType{}, "example.Custom", &CustomSerializer{})
关于 ExtensionSerializer 接口实现,请参考 自定义序列化器。
注册作用域
类型注册是 Fory 实例级别 的:
f1 := fory.New()
f2 := fory.New()
// Types registered on f1 are NOT available on f2
f1.RegisterStruct(User{}, 1)
// f2 cannot deserialize User unless also registered
f2.RegisterStruct(User{}, 1)
注册时机
应在创建 Fory 实例后、首次序列化/反序列化之前完成类型注册:
f := fory.New()
// Register before use
f.RegisterStruct(User{}, 1)
f.RegisterStruct(Order{}, 2)
// Now serialize/deserialize
data, _ := f.Serialize(&User{ID: 1, Name: "Alice"})
嵌套类型注册
对象图中的所有结构体类型(包括嵌套类型)都应注册:
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address Address
}
f := fory.New()
// Register ALL struct types used in the object graph
f.RegisterStruct(Address{}, 1)
f.RegisterStruct(Person{}, 2)
跨语言注册
进行跨语言序列化时,必须在所有语言中保持一致注册。
使用 ID
所有语言使用同一个数值 ID:
Go:
f.RegisterStruct(User{}, 1)