FastJSON 对 `Integer` 类型的编解码(序列化和反序列化)

FastJSON 对 Integer 类型的编解码(序列化和反序列化)是通过内置的 IntegerCodec 类实现的。FastJSON 在初始化时,会通过 ParserConfig 和 SerializeConfig 自动默认注册该编解码器。

FastJSON 对 Integer 类型的编解码(序列化和反序列化)是通过内置的 IntegerCodec 类实现的。本文基于 fastjson-1.2.83 讲解其核心实现逻辑和源码分析。


1. 源码定位

FastJSON 的 Integer 编解码逻辑位于 com.alibaba.fastjson.serializer.IntegerCodec 类中。该类实现了 ObjectSerializerObjectDeserializer 接口,分别负责序列化和反序列化。

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());
 }
}

关键点:

  1. 直接写入整数值:将 Integer(或Long) 转换为 基本类型int(或long) 后直接输出,避免装箱/拆箱。
  2. 处理 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;
}

关键点:

  1. 支持多种输入格式
    • JSON 整数(123)直接解析为 Integer
    • JSON 字符串("123")转换为 Integer
    • JSON null 解析为 null
    • 其他类型(如浮点数 123.0123.5)通过 Number 类型转换,可能会丢失精度哦。
  2. 严格的类型检查:非法格式(如非数字字符串)会抛出JSONException异常。

4. 编解码器注册

FastJSON 在初始化时,会通过 ParserConfigSerializeConfig 自动注册默认编解码器。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 的编解码做了以下优化:

  1. 避免对象创建:直接操作原始类型 int,减少装箱/拆箱。
  2. 快速路径(Fast Path):针对常见的整数输入格式(如 JSONToken.LITERAL_INT)直接解析。
  3. 缓存常用值: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 的高效编解码,核心逻辑包括:

  1. 直接操作原始类型(int等基础类型,primitive type)避免性能损耗。
  2. 支持多种输入格式(整数、字符串、其他数字类型)。
  3. 严格校验非法输入,保证数据安全。

这种设计模式可以完全复用到自定义类型(如 Money)的编解码实现中。

作者:buguge原文地址:https://www.cnblogs.com/buguge/p/18838633

%s 个评论

要回复文章请先登录注册