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

打印 上一主题 下一主题

主题 1739|帖子 1739|积分 5217

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
FastJSON 对 Integer 类型的编解码(序列化和反序列化)是通过内置的 IntegerCodec 类实现的。FastJSON 在初始化时,会通过 ParserConfig 和 SerializeConfig 自动默认注册该编解码器。
FastJSON 对 Integer 类型的编解码(序列化和反序列化)是通过内置的 IntegerCodec 类实现的。本文基于 fastjson-1.2.83 解说其核心实现逻辑和源码分析。
1. 源码定位

FastJSON 的 Integer 编解码逻辑位于 com.alibaba.fastjson.serializer.IntegerCodec 类中。该类实现了 ObjectSerializer 和 ObjectDeserializer 接口,分别负责序列化和反序列化。
  1. package com.alibaba.fastjson.serializer;
  2. public class IntegerCodec implements ObjectSerializer, ObjectDeserializer {
  3.     public static IntegerCodec instance = new IntegerCodec();
  4.     public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
  5.         throws IOException {
  6.         ...
  7.     }
  8.    
  9.     public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
  10.         ...
  11.     }
  12.     public int getFastMatchToken() {
  13.         return JSONToken.LITERAL_INT; // 整数字面量
  14.     }
  15. }
复制代码
2. 序列化源码(Integer → JSON)

入口方法: IntegerCodec#write
  1. public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
  2.     SerializeWriter out = serializer.out;
  3.     Number value = (Number) object;
  4.     if (value == null) {
  5.         out.writeNull(); // 处理 null 值
  6.         return;
  7.     }
  8.     // 直接输出整数
  9.     if (object instanceof Long) {
  10.         out.writeLong(value.longValue());
  11.     } else {
  12.         out.writeInt(value.intValue());
  13.     }
  14. }
复制代码
关键点:


  • 直接写入整数值:将 Integer(或Long) 转换为 基本类型int(或long) 后直接输出,制止装箱/拆箱。
  • 处置惩罚 null 值:如果输入为 null,输出 JSON 的 null。
3. 反序列化源码(JSON → Integer)

入口方法: IntegerCodec#deserialze
  1. // 输入:parser-语法解析器(即 JSON 解析器),包含词法分析器 (lexer)
  2.         clazz-目标类型(如 Integer.class 或 AtomicInteger.class)
  3.         fieldName-当前字段名(用于错误提示)
  4. // 输出:反序列化后的对象(Integer 或 AtomicInteger)
  5. public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
  6.     final JSONLexer lexer = parser.lexer; // lexer-词法分析器
  7.     final int token = lexer.token(); // token-词法单元
  8.     // 处理 JSON 空值 。当检测到 null 值时,跳过当前 token 并返回 null
  9.     if (token == JSONToken.NULL) {
  10.         lexer.nextToken(JSONToken.COMMA);
  11.         return null;
  12.     }
  13.     Integer intObj;
  14.     try {
  15.         if (token == JSONToken.LITERAL_INT) { // 整数字面量
  16.             int val = lexer.intValue();
  17.             lexer.nextToken(JSONToken.COMMA);
  18.             intObj = Integer.valueOf(val);
  19.         } else if (token == JSONToken.LITERAL_FLOAT) { // 浮点数字面量
  20.             BigDecimal number = lexer.decimalValue();
  21.             intObj = TypeUtils.intValue(number); // 浮点转整数,截断小数(非四舍五入,可能丢失精度)
  22.             lexer.nextToken(JSONToken.COMMA);
  23.         } else {
  24.             if (token == JSONToken.LBRACE) { // 当 JSON 值为对象(如 {"$value": 123})时,解析整个对象并通过 TypeUtils 转换
  25.                 JSONObject jsonObject = new JSONObject(true);
  26.                 parser.parseObject(jsonObject);
  27.                 intObj = TypeUtils.castToInt(jsonObject);
  28.             } else { // 兜底处理。处理非基础类型(如字符串 "123"、布尔值等)的转换
  29.                 Object value = parser.parse();
  30.                 intObj = TypeUtils.castToInt(value);
  31.             }
  32.         }
  33.     } catch (Exception ex) { // 异常封装:统一抛出 JSONException 避免底层异常泄露
  34.         String message = "parseInt error";
  35.         if (fieldName != null) {
  36.             message += (", field : " + fieldName);
  37.         }
  38.         throw new JSONException(message, ex); // 带字段名的错误提示(附加字段信息便于调试)
  39.     }
  40.     // 通过 clazz 参数确保返回类型正确性(Integer或 AtomicInteger)
  41.     if (clazz == AtomicInteger.class) {
  42.         return (T) new AtomicInteger(intObj.intValue());
  43.     }
  44.     return (T) intObj;
  45. }
复制代码
关键点:


  • 支持多种输入格式

    • JSON 整数(123)直接解析为 Integer。
    • JSON 字符串("123")转换为 Integer。
    • JSON null 解析为 null。
    • 其他类型(如浮点数 123.0 123.5)通过 Number 类型转换,可能会丢失精度哦。

  • 严格的类型检查:非法格式(如非数字字符串)会抛出JSONException异常。
4. 编解码器注册

FastJSON 在初始化时,会通过 ParserConfig 和 SerializeConfig 自动注册默认编解码器。IntegerCodec 的注册逻辑如下:
源码片断(ParserConfig#initDeserializers)
  1. // 反序列化器注册
  2. deserializers.put(Integer.class, IntegerCodec.instance);
  3. deserializers.put(int.class, IntegerCodec.instance);
复制代码
源码片断(SerializeConfig#initSerializers)
  1. // 序列化器注册
  2. put(Integer.class, IntegerCodec.instance);
  3. put(int.class, IntegerCodec.instance);
复制代码
5. 性能优化

FastJSON 对 Integer 的编解码做了以下优化:

  • 制止对象创建:直接操作原始类型 int,减少装箱/拆箱。
  • 快速路径(Fast Path):针对常见的整数输入格式(如 JSONToken.LITERAL_INT)直接解析。
  • 缓存常用值:JVM 对 Integer 的缓存(-128~127)被隐式利用,减少对象创建。
6. 示例:序列化与反序列化过程

序列化过程(Integer → JSON)
  1. Integer num = 100;
  2. String json = JSON.toJSONString(num); // 输出: 100
复制代码
反序列化过程(JSON → Integer)
  1. String json = "200";
  2. Integer num = JSON.parseObject(json, Integer.class); // 结果: 200
复制代码
7. 扩展应用场景

1. 自定义类型处置惩罚器

可继承 IntegerCodec 覆盖 deserialze 方法,实现如:
  1. // 处理十六进制字符串 "0xFF" → 255
  2. if (token == JSONToken.LITERAL_STRING) {
  3.     String hex = lexer.stringVal();
  4.     return Integer.parseInt(hex.substring(2), 16);
  5. }
复制代码
2. 结合注解使用

通过 @JSONField(deserializeUsing = CustomIntegerCodec.class) 指定自定义解析器
总结

FastJSON 通过 IntegerCodec 实现了 Integer 的高效编解码,核心逻辑包括:

  • 直接操作原始类型(int等底子类型,primitive type)制止性能损耗。
  • 支持多种输入格式(整数、字符串、其他数字类型)。
  • 严格校验非法输入,包管数据安全。
这种设计模式可以完全复用到自定义类型(如 Money)的编解码实现中。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

千千梦丶琪

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表