FastJSON 对 `Integer` 类型的编解码(序列化和反序列化),FastJSON在初
FastJSON 对 `Integer` 类型的编解码(序列化和反序列化),FastJSON在初
FastJSON 对
Integer
类型的编解码(序列化和反序列化)是通过内置的IntegerCodec
类实现的。FastJSON 在初始化时,会通过 ParserConfig 和 SerializeConfig 自动默认注册该编解码器。
FastJSON 对 Integer
类型的编解码(序列化和反序列化)是通过内置的 IntegerCodec
类实现的。本文基于 fastjson-1.2.83 讲解其核心实现逻辑和源码分析。
1. 源码定位
FastJSON 的 Integer
编解码逻辑位于 com.alibaba.fastjson.serializer.IntegerCodec
类中。该类实现了 ObjectSerializer
和 ObjectDeserializer
接口,分别负责序列化和反序列化。
package com.alibaba.fastjson.serializer;
public class IntegerCodec implements ObjectSerializer, ObjectDeserializer {
public static IntegerCodec instance = new IntegerCodec();
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
throws IOException {
...
}
public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
...
}
public int getFastMatchToken() {
return JSONToken.LITERAL_INT; // 整数字面量
}
}
2. 序列化源码(Integer
→ JSON)
入口方法: IntegerCodec#write
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
SerializeWriter out = serializer.out;
Number value = (Number) object;
if (value == null) {
out.writeNull(); // 处理 null 值
return;
}
// 直接输出整数
if (object instanceof Long) {
out.writeLong(value.longValue());
} else {
out.writeInt(value.intValue());
}
}
关键点:
- 直接写入整数值:将
Integer
(或Long
) 转换为 基本类型int
(或long
) 后直接输出,避免装箱/拆箱。 - 处理 null 值:如果输入为
null
,输出 JSON 的null
。
3. 反序列化源码(JSON → Integer
)
入口方法: IntegerCodec#deserialze
// 输入:parser-语法解析器(即 JSON 解析器),包含词法分析器 (lexer)
clazz-目标类型(如 Integer.class 或 AtomicInteger.class)
fieldName-当前字段名(用于错误提示)
// 输出:反序列化后的对象(Integer 或 AtomicInteger)
public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
final JSONLexer lexer = parser.lexer; // lexer-词法分析器
final int token = lexer.token(); // token-词法单元
// 处理 JSON 空值 。当检测到 null 值时,跳过当前 token 并返回 null
if (token == JSONToken.NULL) {
lexer.nextToken(JSONToken.COMMA);
return null;
}
Integer intObj;
try {
if (token == JSONToken.LITERAL_INT) { // 整数字面量
int val = lexer.intValue();
lexer.nextToken(JSONToken.COMMA);
intObj = Integer.valueOf(val);
} else if (token == JSONToken.LITERAL_FLOAT) { // 浮点数字面量
BigDecimal number = lexer.decimalValue();
intObj = TypeUtils.intValue(number); // 浮点转整数,截断小数(非四舍五入,可能丢失精度)
lexer.nextToken(JSONToken.COMMA);
} else {
if (token == JSONToken.LBRACE) { // 当 JSON 值为对象(如 {"$value": 123})时,解析整个对象并通过 TypeUtils 转换
JSONObject jsonObject = new JSONObject(true);
parser.parseObject(jsonObject);
intObj = TypeUtils.castToInt(jsonObject);
} else { // 兜底处理。处理非基础类型(如字符串 "123"、布尔值等)的转换
Object value = parser.parse();
intObj = TypeUtils.castToInt(value);
}
}
} catch (Exception ex) { // 异常封装:统一抛出 JSONException 避免底层异常泄露
String message = "parseInt error";
if (fieldName != null) {
message += (", field : " + fieldName);
}
throw new JSONException(message, ex); // 带字段名的错误提示(附加字段信息便于调试)
}
// 通过 clazz 参数确保返回类型正确性(Integer或 AtomicInteger)
if (clazz == AtomicInteger.class) {
return (T) new AtomicInteger(intObj.intValue());
}
return (T) intObj;
}
关键点:
- 支持多种输入格式:
- JSON 整数(
123
)直接解析为Integer
。 - JSON 字符串(
"123"
)转换为Integer
。 - JSON
null
解析为null
。 - 其他类型(如浮点数
123.0
123.5
)通过Number
类型转换,可能会丢失精度哦。
- JSON 整数(
- 严格的类型检查:非法格式(如非数字字符串)会抛出
JSONException
异常。
4. 编解码器注册
FastJSON 在初始化时,会通过 ParserConfig
和 SerializeConfig
自动注册默认编解码器。IntegerCodec
的注册逻辑如下:
源码片段(ParserConfig#initDeserializers
)
// 反序列化器注册
deserializers.put(Integer.class, IntegerCodec.instance);
deserializers.put(int.class, IntegerCodec.instance);
源码片段(SerializeConfig#initSerializers
)
// 序列化器注册
put(Integer.class, IntegerCodec.instance);
put(int.class, IntegerCodec.instance);
5. 性能优化
FastJSON 对 Integer
的编解码做了以下优化:
- 避免对象创建:直接操作原始类型
int
,减少装箱/拆箱。 - 快速路径(Fast Path):针对常见的整数输入格式(如
JSONToken.LITERAL_INT
)直接解析。 - 缓存常用值:JVM 对
Integer
的缓存(-128~127)被隐式利用,减少对象创建。
6. 示例:序列化与反序列化过程
序列化过程(Integer
→ JSON)
Integer num = 100;
String json = JSON.toJSONString(num); // 输出: 100
反序列化过程(JSON → Integer
)
String json = "200";
Integer num = JSON.parseObject(json, Integer.class); // 结果: 200
7. 扩展应用场景
1. 自定义类型处理器
可继承 IntegerCodec 覆盖 deserialze 方法,实现如:
// 处理十六进制字符串 "0xFF" → 255
if (token == JSONToken.LITERAL_STRING) {
String hex = lexer.stringVal();
return Integer.parseInt(hex.substring(2), 16);
}
2. 结合注解使用
通过 @JSONField(deserializeUsing = CustomIntegerCodec.class)
指定自定义解析器
总结
FastJSON 通过 IntegerCodec
实现了 Integer
的高效编解码,核心逻辑包括:
- 直接操作原始类型(int等基础类型,primitive type)避免性能损耗。
- 支持多种输入格式(整数、字符串、其他数字类型)。
- 严格校验非法输入,保证数据安全。
这种设计模式可以完全复用到自定义类型(如 Money
)的编解码实现中。
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/18838633
用户点评