跳到主要内容
版本:dev

枚举配置

本页说明如何在 Apache Fory 中配置 Java 枚举的序列化方式。

默认枚举行为

Java 枚举可以通过两种模式进行序列化:

  1. 按数值 tag:默认行为
  2. 按枚举名称:通过 serializeEnumByName(true) 启用

在 xlang 模式下,始终使用数值 tag。在原生 Java 模式下,serializeEnumByName(true) 会把枚举序列化方式切换为按名称,而不是按数值 tag。

按名称序列化枚举

当原生 Java 对端应按名称而不是按数值 tag 匹配枚举常量时,请使用 serializeEnumByName(true)

Fory fory = Fory.builder()
.withLanguage(Language.JAVA)
.serializeEnumByName(true)
.build();

当声明顺序可能不稳定,但枚举名称保持固定时,这种模式很有用。它只影响原生 Java 模式;xlang 仍然使用数值 tag。

稳定的数值枚举 ID

如果未启用 serializeEnumByName(true),Java 枚举会按数值 tag 序列化。默认的 tag 是声明顺序对应的 ordinal。如果枚举需要与声明顺序无关的稳定 ID,请只使用一种 @ForyEnumId 来源:要么标注唯一一个 ID 来源,要么为每个枚举常量都显式标注 tag 值。

import org.apache.fory.annotation.ForyEnumId;

enum Status {
Unknown(10),
Running(20),
Finished(30);

private final int id;

Status(int id) {
this.id = id;
}

@ForyEnumId
public int getId() {
return id;
}
}

Java 也支持在某个枚举实例字段上标注 @ForyEnumId,或者直接在每个枚举常量上标注,例如 @ForyEnumId(10) Unknown

@ForyEnumId 的三种样式

@ForyEnumId 只支持以下三种配置方式:

  1. 标注一个枚举实例字段,并在该字段中保存数值 ID
  2. 标注一个无参 public 实例方法,例如 getId()
  3. 为每个枚举常量都直接标注显式值,例如 @ForyEnumId(10) Unknown

校验规则

  1. 对于同一个枚举,只能使用上述三种方式中的一种
  2. 字段和方法上的注解必须保持 value() 为默认值 -1
  3. 一旦有任意一个枚举常量使用 @ForyEnumId,所有枚举常量都必须标注
  4. 所有 ID 都必须非负、唯一,并且能放入 Java int

查找行为

  1. 没有 @ForyEnumId 时,Fory 写入声明顺序对应的 ordinal
  2. 使用 @ForyEnumId 时,Fory 会改为写入配置好的稳定数值 tag
  3. 对于较小且稠密的 tag,内部会使用数组查找;对稀疏且较大的 tag,则退回到 map 查找

如何在名称模式和数值模式之间选择

  • 当枚举只在 Java 内部使用,且常量名才是兼容性主键时,使用枚举名称
  • 当需要处理跨语言载荷,或需要稳定的显式 ID 时,使用数值 tag
  • 当声明顺序可能变化,但编码格式中的数值 ID 必须保持稳定时,使用 @ForyEnumId

相关主题