生成代码
本文档说明各目标语言的代码生成结果与结构。
Fory IDL 生成的类型遵循宿主语言习惯,可直接作为领域对象使用。生成代码同时包含 to/from bytes 辅助方法和类型注册辅助逻辑。
参考 Schema
下面示例基于两个真实 schema:
addressbook.fdl(显式类型 ID)auto_id.fdl(未显式声明类型 ID)
addressbook.fdl(节选)
package addressbook;
option go_package = "github.com/myorg/myrepo/gen/addressbook;addressbook";
message Person [id=100] {
string name = 1;
int32 id = 2;
enum PhoneType [id=101] {
PHONE_TYPE_MOBILE = 0;
PHONE_TYPE_HOME = 1;
PHONE_TYPE_WORK = 2;
}
message PhoneNumber [id=102] {
string number = 1;
PhoneType phone_type = 2;
}
list<PhoneNumber> phones = 7;
Animal pet = 8;
}
message Dog [id=104] {
string name = 1;
int32 bark_volume = 2;
}
message Cat [id=105] {
string name = 1;
int32 lives = 2;
}
union Animal [id=106] {
Dog dog = 1;
Cat cat = 2;
}
message AddressBook [id=103] {
list<Person> people = 1;
map<string, Person> people_by_name = 2;
}
auto_id.fdl(节选)
package auto_id;
enum Status {
UNKNOWN = 0;
OK = 1;
}
message Envelope {
string id = 1;
message Payload {
int32 value = 1;
}
union Detail {
Payload payload = 1;
string note = 2;
}
Payload payload = 2;
Detail detail = 3;
Status status = 4;
}
union Wrapper {
Envelope envelope = 1;
string raw = 2;
}
Java
输出布局
对于 package addressbook,Java 输出通常位于:
- Java 输出目录:
<java_out>/addressbook/ - 类型文件:
AddressBook.java、Person.java、Dog.java、Cat.java、Animal.java - 注册辅助类:
AddressbookForyRegistration.java
类型生成
message 会生成带 @ForyField、默认构造器、getter/setter 以及字节辅助方法的 Java 类:
public class Person {
public static enum PhoneType {
MOBILE,
HOME,
WORK;
}
public static class PhoneNumber {
@ForyField(id = 1)
private String number;
@ForyField(id = 2)
private PhoneType phoneType;
public byte[] toBytes() { ... }
public static PhoneNumber fromBytes(byte[] bytes) { ... }
}
@ForyField(id = 1)
private String name;
@ForyField(id = 8)
private Animal pet;
public byte[] toBytes() { ... }
public static Person fromBytes(byte[] bytes) { ... }
}
union 会生成继承 org.apache.fory.type.union.Union 的类:
public final class Animal extends Union {
public enum AnimalCase {
DOG(1),
CAT(2);
public final int id;
AnimalCase(int id) { this.id = id; }
}
public static Animal ofDog(Dog v) { ... }
public AnimalCase getAnimalCase() { ... }
public int getAnimalCaseId() { ... }
public boolean hasDog() { ... }
public Dog getDog() { ... }
public void setDog(Dog v) { ... }
}
注册
生成的注册辅助方法:
public static void register(Fory fory) {
org.apache.fory.resolver.TypeResolver resolver = fory.getTypeResolver();
resolver.registerUnion(Animal.class, 106L, new org.apache.fory.serializer.UnionSerializer(fory, Animal.class));
resolver.register(Person.class, 100L);
resolver.register(Person.PhoneType.class, 101L);
resolver.register(Person.PhoneNumber.class, 102L);
resolver.register(Dog.class, 104L);
resolver.register(Cat.class, 105L);
resolver.register(AddressBook.class, 103L);
}
对于未显式 [id=...] 的 schema,注册代码会使用计算得到的数值 ID(例如 auto_id.fdl):
resolver.register(Status.class, 1124725126L);
resolver.registerUnion(Wrapper.class, 1471345060L, new org.apache.fory.serializer.UnionSerializer(fory, Wrapper.class));
resolver.register(Envelope.class, 3022445236L);
resolver.registerUnion(Envelope.Detail.class, 1609214087L, new org.apache.fory.serializer.UnionSerializer(fory, Envelope.Detail.class));
resolver.register(Envelope.Payload.class, 2862577837L);
若设置 option enable_auto_type_id = false;,则按命名空间与类型名注册:
resolver.register(Config.class, "myapp.models", "Config");
resolver.registerUnion(
Holder.class,
"myapp.models",
"Holder",
new org.apache.fory.serializer.UnionSerializer(fory, Holder.class));
使用示例
Person person = new Person();
person.setName("Alice");
person.setPet(Animal.ofDog(new Dog()));
byte[] data = person.toBytes();
Person restored = Person.fromBytes(data);
Python
输出布局
Python 每个 schema 文件生成一个模块,例如:
- Python 输出文件:
<python_out>/addressbook.py
类型生成
union 生成 case 枚举与 Union 子类,并提供类型化辅助方法:
class AnimalCase(Enum):
DOG = 1
CAT = 2
class Animal(Union):
@classmethod
def dog(cls, v: Dog) -> "Animal": ...
def case(self) -> AnimalCase: ...
def case_id(self) -> int: ...
def is_dog(self) -> bool: ...
def dog_value(self) -> Dog: ...
def set_dog(self, v: Dog) -> None: ...
message 生成 @pyfory.dataclass 类型,嵌套类型保持嵌套:
@pyfory.dataclass
class Person:
class PhoneType(IntEnum):
MOBILE = 0
HOME = 1
WORK = 2
@pyfory.dataclass
class PhoneNumber:
number: str = pyfory.field(id=1, default="")
phone_type: Person.PhoneType = pyfory.field(id=2, default=None)
name: str = pyfory.field(id=1, default="")
phones: List[Person.PhoneNumber] = pyfory.field(id=7, default_factory=list)
pet: Animal = pyfory.field(id=8, default=None)
def to_bytes(self) -> bytes: ...
@classmethod
def from_bytes(cls, data: bytes) -> "Person": ...
注册
生成注册函数:
def register_addressbook_types(fory: pyfory.Fory):
fory.register_union(Animal, type_id=106, serializer=AnimalSerializer(fory))
fory.register_type(Person, type_id=100)
fory.register_type(Person.PhoneType, type_id=101)
fory.register_type(Person.PhoneNumber, type_id=102)
fory.register_type(Dog, type_id=104)
fory.register_type(Cat, type_id=105)
fory.register_type(AddressBook, type_id=103)
未显式 [id=...] 时,注册代码使用计算得到的数值 ID:
fory.register_type(Status, type_id=1124725126)
fory.register_union(Wrapper, type_id=1471345060, serializer=WrapperSerializer(fory))
fory.register_type(Envelope, type_id=3022445236)
fory.register_union(Envelope.Detail, type_id=1609214087, serializer=Envelope.DetailSerializer(fory))
fory.register_type(Envelope.Payload, type_id=2862577837)
若设置 option enable_auto_type_id = false;:
fory.register_type(Config, namespace="myapp.models", typename="Config")
fory.register_union(
Holder,
namespace="myapp.models",
typename="Holder",
serializer=HolderSerializer(fory),
)
使用示例
person = Person(name="Alice", pet=Animal.dog(Dog(name="Rex", bark_volume=10)))
data = person.to_bytes()
restored = Person.from_bytes(data)