马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
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 类型转换,可能会丢失精度哦。
- 严格的类型检查:非法格式(如非数字字符串)会抛出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)的编解码实现中。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |