













本文以fastjson-1.2.83版本中 EnumDeserializer 类的源码,来解释其工作原理和实现细节。
EnumDeserializer 是 FastJSON 用于将 JSON 反序列化为枚举类型的核心类。它支持:
Enum.name())反序列化Enum.ordinal())反序列化@JSONField 注解指定的别名反序列化protected final Class<?> enumClass; // 枚举类
protected final Enum[] enums; // 按哈希值排序的枚举数组
protected final Enum[] ordinalEnums; // 按序号排序的枚举数组
protected long[] enumNameHashCodes; // 枚举名称哈希值数组(已排序)
构造函数是整个类的核心,它预先计算了所有枚举常量的哈希值:
ordinalEnums = (Enum[]) enumClass.getEnumConstants();
Map<Long, Enum> enumMap = new HashMap<Long, Enum>();
for (int i = 0; i < ordinalEnums.length; ++i) {
Enum e = ordinalEnums[i];
String name = e.name();
// 检查 @JSONField 注解
JSONField jsonField = null;
try {
Field field = enumClass.getField(name);
jsonField = TypeUtils.getAnnotation(field, JSONField.class);
if (jsonField != null) {
String jsonFieldName = jsonField.name();
if (jsonFieldName != null && jsonFieldName.length() > 0) {
name = jsonFieldName; // 使用注解指定的名称
}
}
} catch (Exception ex) {
// skip
}
// 计算原始名称的哈希
long hash = fnv1a_64_magic_hashcode;
for (int j = 0; j < name.length(); ++j) {
char ch = name.charAt(j);
hash ^= ch;
hash *= fnv1a_64_magic_prime;
}
enumMap.put(hash, e);
// 计算小写名称的哈希(用于大小写不敏感匹配)
long hash_lower = fnv1a_64_magic_hashcode;
for (int j = 0; j < name.length(); ++j) {
char ch = name.charAt(j);
char lowerCh = (ch >= 'A' && ch <= 'Z') ? (char)(ch + 32) : ch;
hash_lower ^= lowerCh;
hash_lower *= fnv1a_64_magic_prime;
}
if (hash != hash_lower) {
enumMap.put(hash_lower, e);
}
// 处理 @JSONField.alternateNames() 备选名称
if (jsonField != null) {
for (String alterName : jsonField.alternateNames()) {
long alterNameHash = fnv1a_64_magic_hashcode;
for (int j = 0; j < alterName.length(); ++j) {
char ch = alterName.charAt(j);
alterNameHash ^= ch;
alterNameHash *= fnv1a_64_magic_prime;
}
if (alterNameHash != hash && alterNameHash != hash_lower) {
enumMap.put(alterNameHash, e);
}
}
}
}
// 提取所有哈希值并排序
this.enumNameHashCodes = new long[enumMap.size()];
int i = 0;
for (Long h : enumMap.keySet()) {
enumNameHashCodes[i++] = h;
}
Arrays.sort(this.enumNameHashCodes);
// 按排序后的哈希值顺序存储枚举
this.enums = new Enum[enumNameHashCodes.length];
for (int j = 0; j < this.enumNameHashCodes.length; ++j) {
long hash = enumNameHashCodes[j];
Enum e = enumMap.get(hash);
this.enums[j] = e;
}
deserialze 方法是实际执行反序列化的入口:
if (token == JSONToken.LITERAL_INT) {
int intValue = lexer.intValue();
lexer.nextToken(JSONToken.COMMA);
if (intValue < 0 || intValue >= ordinalEnums.length) {
throw new JSONException("parse enum " + enumClass.getName() + " error, value : " + intValue);
}
return (T) ordinalEnums[intValue];
}
else if (token == JSONToken.LITERAL_STRING) {
String name = lexer.stringVal();
lexer.nextToken(JSONToken.COMMA);
if (name.length() == 0) {
return (T) null; // 空字符串返回 null
}
// 计算输入字符串的哈希
long hash = fnv1a_64_magic_hashcode;
long hash_lower = fnv1a_64_magic_hashcode;
for (int j = 0; j < name.length(); ++j) {
char ch = name.charAt(j);
hash ^= ch;
hash_lower ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);
hash *= fnv1a_64_magic_prime;
hash_lower *= fnv1a_64_magic_prime;
}
// 首先尝试原始哈希
Enum e = getEnumByHashCode(hash);
// 如果没找到,尝试小写哈希
if (e == null && hash_lower != hash) {
e = getEnumByHashCode(hash_lower);
}
if (e == null && lexer.isEnabled(Feature.ErrorOnEnumNotMatch)) {
throw new JSONException("not match enum value, " + enumClass.getName() + " : " + name);
}
return (T) e;
}
public Enum getEnumByHashCode(long hashCode) {
if (enums == null) {
return null;
}
// 二分查找已排序的哈希数组
int enumIndex = Arrays.binarySearch(this.enumNameHashCodes, hashCode);
if (enumIndex < 0) {
return null; // 没找到
}
return enums[enumIndex];
}
// 原始大小写
hash ^= ch;
hash *= fnv1a_64_magic_prime;
// 转换为小写(如果是大写字母)
hash_lower ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);
hash_lower *= fnv1a_64_magic_prime;
这样实现了大小写不敏感的枚举匹配,用户输入 "YCX" 或 "ycx" 都能匹配到 YCX 枚举。
enumNameHashCodes[] 和 enums[]// 初始化哈希值
long hash = fnv1a_64_magic_hashcode;
// 迭代计算
for (int j = 0; j < name.length(); ++j) {
char ch = name.charAt(j);
hash ^= ch; // XOR
hash *= fnv1a_64_magic_prime; // 乘以质数
}
public enum Status {
@JSONField(name = "success", alternateNames = {"ok", "good"})
SUCCESS,
@JSONField(name = "failed", alternateNames = {"error", "bad"})
FAILED,
PENDING
}
0 → SUCCESS"SUCCESS" → SUCCESS"success" → SUCCESS"ok" 或 "good" → SUCCESS"Success" 或 "success" → SUCCESSintValue < 0 || intValue >= ordinalEnums.length → 抛出异常Feature.ErrorOnEnumNotMatch)getEnumByHashCode 方法"生产"枚举实例| 特性 | FastJSON EnumDeserializer | Jackson | Gson |
|---|---|---|---|
| 哈希算法 | FNV-1a 64位 | 无 | 无 |
| 查找方式 | 二分查找 | 线性查找/HashMap | 线性查找 |
| 大小写不敏感 | 支持 | 配置支持 | 配置支持 |
| 注解支持 | @JSONField |
@JsonCreator |
@SerializedName |
| 性能 | 高 | 中 | 中 |
EnumDeserializer 的设计体现了 FastJSON 在性能优化上的追求:
这个实现平衡了性能、功能和内存使用,是 FastJSON 高效反序列化的一个典型代表。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。