原创 剑九 2025-10-15 18:31 上海
Fastjson1.X版本目前已停止维护,被Fastjson2.X代替,但1.X版本国内被广泛使用,通过学习其技术架构,剖析架构上优缺点,对技术人员提升软件设计工程实践能力很有价值。

💡 **Fastjson 1.x 架构概览与价值**:Fastjson 1.x 是阿里巴巴开源的高性能 JSON 库,尽管已停止维护并由 2.x 版本替代,但其在国内的广泛应用使其技术架构的学习对提升软件设计能力仍具价值。文章从用户接口、配置管理、序列化/反序列化引擎及安全防护层等高层视角,勾勒出框架的整体结构。
🚀 **核心序列化与反序列化机制**:文章详细解析了 Fastjson 的序列化(Java对象转JSON字符串)和反序列化(JSON字符串转Java对象)的核心流程。序列化通过`JSONSerializer`和`SerializeWriter`,利用策略模式查找`ObjectSerializer`,并结合ASM字节码技术或反射实现高效转换。反序列化则由`DefaultJSONParser`和`JSONLexer`驱动,通过`ObjectDeserializer`进行类型匹配和字段填充,同样支持ASM优化。
⚙️ **关键特性深入剖析**:Fastjson 1.x 的高性能得益于多项关键技术。例如,**ASM性能优化**通过动态生成字节码,直接调用方法绕过反射开销;**AutoType机制**允许在反序列化时指定目标类,增加了灵活性但也带来了安全隐患;**流式解析**则通过`SerializeWriter`和`JSONLexer`的高效缓冲区管理,减少了内存分配和字符串拼接的成本。
🔗 **上下文管理与安全防护**:在序列化过程中,Fastjson 采用DFS算法和`SerialContext`管理对象树,通过`references`(`IdentityHashMap`)实现**循环引用检测**,防止栈溢出,并用`$ref`占位符标记。反序列化阶段则通过`ParserConfig`和`Feature`等控制解析行为,并提供`AutoType`的黑白名单机制来加强安全防护。
📚 **项目结构与源码解读**:文章展示了 Fastjson 的清晰项目结构,将功能划分为`parser`、`serializer`、`annotation`等核心模块。通过对`JSON.java`、`JSONSerializer.java`、`DefaultJSONParser.java`等关键类的源码解读,结合时序图和数据流图,深入剖析了序列化和反序列化的具体实现细节,为开发者提供了详实的学习资料。
原创 剑九 2025-10-15 18:31 上海
Fastjson1.X版本目前已停止维护,被Fastjson2.X代替,但1.X版本国内被广泛使用,通过学习其技术架构,剖析架构上优缺点,对技术人员提升软件设计工程实践能力很有价值。
com.alibaba.fastjson/├── JSON.java # 核心入口类├── annotation/ # 注解定义├── asm/ # ASM字节码精简库├── parser/ # 解析器模块│ ├── DefaultJSONParser.java # 默认JSON解析器│ ├── JSONLexer.java # 词法分析器接口│ ├── JSONScanner.java # 词法分析器实现│ └── deserializer/ # 反序列化器├── serializer/ # 序列化器模块│ ├── JSONSerializer.java # JSON序列化器│ ├── SerializeConfig.java # 序列化配置│ └── ObjectSerializer.java # 对象序列化器接口├── spi/ # SPI扩展机制├── support/ # 框架支持└── util/ # 工具类
用户调用toJSONString方法进行对象序列化操作,JSON.java包含了多个toJSONString重载方法,共同完成核心类初始化:SerializeConfig,SerializeWriter,JSONSerializer。Person person = new Person();String json = JSON.toJSONString(person);
序列化控制流程JSONSerializer.write()核心逻辑write方法的逻辑比较简单,首先处理null值,然后根据类型查找序列器(ObjectSerializer),最后将序列化逻辑委派给序列化器处理。//用户不指定SerializeConfig,默认私有全局配置public static String toJSONString(Objectobject, SerializeFilter[] filters,SerializerFeature... features) {return toJSONString(object, SerializeConfig.globalInstance, filters, null, DEFAULT_GENERATE_FEATURE, features);}public static String toJSONString(Objectobject,SerializeConfig config,SerializeFilter[] filters,String dateFormat,int defaultFeatures,SerializerFeature... features) {SerializeWriter out = new SerializeWriter((Writer) null, defaultFeatures, features);try {JSONSerializer serializer = new JSONSerializer(out);//省略其他代码...serializer.write(object); // 核心序列化调用return out.toString();} finally {out.close();}}
类型识别与序列化器策略框架采用策略化模式将不同类型序列化逻辑封装成不同的序列化器:基础类型 : 使用专门的Codec(如StringCodec、IntegerCodec)集合类型 : 使用ListSerializer、MapSerializer等JavaBean : 使用JavaBeanSerializer或ASM动态生成的序列化器枚举类型 : 使用EnumSerializerSerializeConfig.getObjectWriter方法负责序列化器查找工作:public final void write(Objectobject) {//如何序列化对象为null,直接写入"null"字符串if (object == null) {out.writeNull();return;}Class<?> clazz = object.getClass();ObjectSerializer writer = getObjectWriter(clazz); // 类型识别与序列化器选择try {writer.write(this, object, null, null, 0); // 委托给具体序列化器} catch (IOException e) {throw new JSONException(e.getMessage(), e);}}
JavaBean序列化处理JavaBeanSerializer的write方法实现了Java对象序列化处理核心逻辑:方法签名分析:public ObjectSerializer getObjectWriter(Class<?> clazz, boolean create) {// 第一步:缓存查找ObjectSerializer writer = get(clazz);if (writer != null) {return writer;}// 第二步:SPI扩展加载(当前线程类加载器)try {final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {if (!(o instanceof AutowiredObjectSerializer)) {continue;}AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;for (Type forType : autowired.getAutowiredFor()) {put(forType, autowired);}}} catch (ClassCastException ex) {// skip}writer = get(clazz);if (writer == null) {// 第三步:SPI扩展加载(JSON类加载器)final ClassLoader classLoader = JSON.class.getClassLoader();if (classLoader != Thread.currentThread().getContextClassLoader()) {// 重复SPI加载逻辑...}}// 第四步:模块扩展for (Module module : modules) {writer = module.createSerializer(this, clazz);if (writer != null) {put(clazz, writer);return writer;}}// 第五步:内置类型匹配if (writer == null) {String className = clazz.getName();Class<?> superClass;if (Map.class.isAssignableFrom(clazz)) {put(clazz, writer = MapSerializer.instance);} else if (List.class.isAssignableFrom(clazz)) {put(clazz, writer = ListSerializer.instance);} else if (Collection.class.isAssignableFrom(clazz)) {put(clazz, writer = CollectionCodec.instance);} else if (Date.class.isAssignableFrom(clazz)) {put(clazz, writer = DateCodec.instance);} else if (clazz.isEnum()) {// 枚举处理逻辑} else if (clazz.isArray()) {// 数组处理逻辑} else {// 第六步:JavaBean序列化器创建if (create) {writer = createJavaBeanSerializer(clazz);put(clazz, writer);}}}return writer;}
序列化流程概览:protected void write(JSONSerializer serializer, //JSON序列化器,提供序列化上下文和输出流Object object, //待序列化的Java对象Object fieldName, //字段名称,用于上下文追踪Type fieldType, //字段类型信息int features, //序列化特性标志位boolean unwrapped //是否展开包装,用于嵌套对象处理) throws IOException
循环引用检测:JavaBeanSerializerwriteReference 方法执行循环引用检测,Fastjson使用$ref占位符处理循环引用问题,防止对象循环引用造成解析查询栈溢出。// 1. 空值检查和循环引用处理if (object == null) {out.writeNull();return;}if (writeReference(serializer, object, features)) {return;}// 2. 字段序列化器选择final FieldSerializer[] getters;if (out.sortField) {getters = this.sortedGetters;} else {getters = this.getters;}// 3. 上下文设置和格式判断SerialContext parent = serializer.context;if (!this.beanInfo.beanType.isEnum()) {serializer.setContext(parent, object, fieldName, this.beanInfo.features, features);}// 4.遍历属性序列化器,完成属性序列化for (int i = 0; i < getters.length; ++i) {FieldSerializer fieldSerializer = getters[i];// 获取属性值Object propertyValue = this.processValue(serializer, fieldSerializer.fieldContext, object, fieldInfoName,propertyValue, features);// 写入属性值fieldSerializer.writeValue(serializer, propertyValue);}
上下文管理与引用追踪:序列化采用DFS(深度优先)算法遍历对象树,使用 IdentityHashMap<Object, SerialContext> references 来追踪对象引用:setContext: 建立序列化上下文,记录对象层次关系containsReference: 检查对象是否已被序列化popContext: 序列化完成后清理上下文public boolean writeReference(JSONSerializer serializer, Objectobject, int fieldFeatures) {SerialContext context = serializer.context;int mask = SerializerFeature.DisableCircularReferenceDetect.mask;// 检查是否禁用循环引用检测if (context == null || (context.features & mask) != 0 || (fieldFeatures & mask) != 0) {return false;}// 检查对象是否已存在于引用表中if (serializer.references != null && serializer.references.containsKey(object)) {serializer.writeReference(object); // 写入引用标记return true;}return false;}
字段值转换与序列化FieldSerializer.writeValue()核心逻辑FieldSerializer 的writeValue方法实现了字段值的序列化操作:protected IdentityHashMap<Object, SerialContext> references = null;protected SerialContext context;//使用链表建立序列化上下文引用链,记录对象层次关系public void setContext(SerialContext parent, Objectobject, Object fieldName, int features, int fieldFeatures) {if (out.disableCircularReferenceDetect) {return;}//构建当前上下文到parent上下文引用链this.context = new SerialContext(parent, object, fieldName, features, fieldFeatures);if (references == null) {references = new IdentityHashMap<Object, SerialContext>();}this.references.put(object, context);}//检查对象是否已被序列化,防止重复序列化public boolean containsReference(Object value) {if (references == null) {return false;}SerialContext refContext = references.get(value);if (refContext == null) {return false;}if (value == Collections.emptyMap()) {return false;}Object fieldName = refContext.fieldName;return fieldName == null || fieldName instanceof Integer || fieldName instanceof String;}//清理上下文,将当前序列化上下文指向父亲节点public void popContext() {if (context != null) {this.context = this.context.parent;}}
不同类型的序列化策略基础类型序列化 :直接调用SerializeWriter的对应方法(writeInt、writeString等)复杂对象序列化 :递归调用JSONSerializer.write()方法维护序列化上下文和引用关系应用过滤器和特性配置ASM定制化序列化器加速,下文会进行详细讲解。为序列化的类动态生成定制化的序列化器,避免反射调用开销JSON字符串构建SerializeWriter.java采用线程本地缓冲机制,提供高效的字符串构建:public void writeValue(JSONSerializer serializer, Object propertyValue) throws Exception {// 运行时类型识别Class<?> runtimeFieldClass = propertyValue != null ?propertyValue.getClass() : this.fieldInfo.fieldClass;// 查找属性类型对应的序列化器ObjectSerializer fieldSerializer = serializer.getObjectWriter(runtimeFieldClass);// 处理特殊格式和注解if (format != null && !(fieldSerializer instanceof DoubleSerializer)) {serializer.writeWithFormat(propertyValue, format);return;}// 委托给具体序列化器处理fieldSerializer.write(serializer, propertyValue, fieldInfo.name,fieldInfo.fieldType, fieldFeatures);}
字符缓冲区 : 线程本地char[]数组减少内存分配,避免频繁创建临时数组对象。动态扩容 : 根据内容长度自动调整缓冲区大小。bufLocal初始化创建2048字符的缓冲区,回收阶段当缓冲区大小不超过 BUFFER_THRESHOLD (128KB)时,将其放回ThreadLocal缓存,超过阈值的大缓冲区不缓存,避免内存占用过大。bytesBufLocal专门用于UTF-8编码转换过程,初始缓冲区大小:8KB(1024 * 8),根据字符数量估算所需字节数(字符数 × 3),只有不超过 BUFFER_THRESHOLD 的缓冲区才会被缓存。//用于存储存JSON字符串private final static ThreadLocal<char[]> bufLocal = new ThreadLocal<char[]>();//将字符串转换为UTF-8字节数组private final static ThreadLocal<byte[]> bytesBufLocal = new ThreadLocal<byte[]>();
查找反序列化器在 DefaultJSONParser.java 中选择合适的反序列化器:// JSON.java - 反序列化入口public static <T> T parseObject(String text, Class<T> clazz, int features) {if (text == null) {return null;}DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance(), features);T value = (T) parser.parseObject(clazz);parser.handleResovleTask(value);parser.close();return value;}
ParserConfig.java 负责获取对应类型的反序列化器:// DefaultJSONParser.java - 反序列化器选择public <T> T parseObject(Type type, Object fieldName) {int token = lexer.token();if (token == JSONToken.NULL) {lexer.nextToken();return (T) TypeUtils.optionalEmpty(type);}//从缓存中查找反序列化器ObjectDeserializer deserializer = config.getDeserializer(type);try {if (deserializer.getClass() == JavaBeanDeserializer.class) {return (T) ((JavaBeanDeserializer) deserializer).deserialze(this, type, fieldName, 0);} else {return (T) deserializer.deserialze(this, type, fieldName);}} catch (JSONException e) {throw e;} catch (Throwable e) {throw new JSONException(e.getMessage(), e);}}
反序列化控制流程JavaBeanDeserializer.java 的deserialze实现了反序列化主要处理流程。// ParserConfig.java - 反序列化器获取public ObjectDeserializer getDeserializer(Type type) {ObjectDeserializer deserializer = this.deserializers.get(type);if (deserializer != null) {return deserializer;}//通过Class查找if (type instanceof Class<?>) {return getDeserializer((Class<?>) type, type);}//通过泛型参数查找if (type instanceof ParameterizedType) {Type rawType = ((ParameterizedType) type).getRawType();if (rawType instanceof Class<?>) {return getDeserializer((Class<?>) rawType, type);} else {return getDeserializer(rawType);}}return JavaObjectDeserializer.instance;}
字符串解析阶段(词法分析)JSONLexerBase内部维护词法解析状态机,实现词法分析核心逻辑,下面展示了Integer值类型处理源码:// JavaBeanDeserializer.java - 类型识别与字段匹配public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName, int features, int[] setFlags) {// 1.特殊类型快速处理if (type == JSON.class || type == JSONObject.class) {return (T) parser.parse();}//2.初始化核心组件final JSONLexer lexer = parser.lexer;//3.反序列化上下文管理ParseContext context = parser.getContext();if (object != null && context != null) {context = context.parent;}ParseContext childContext = null;//保存解析后字段值Map<String, Object> fieldValues = null;// JSON关键字分支预处理if (token == JSONToken.RBRACE) {lexer.nextToken(JSONToken.COMMA);if (object == null) {object = createInstance(parser, type);}return (T) object;}//处理其他JSON关键字...//4.字段解析主循环for (int fieldIndex = 0, notMatchCount = 0;; fieldIndex++) {boolean customDeserializer = false;//这是一个性能优化的设计,通过预排序和索引访问来提高字段匹配的效率,//通常情况下JSON串按字段定义顺序排列,因此能快速命中if (fieldIndex < sortedFieldDeserializers.length && notMatchCount < 16) {fieldDeserializer = sortedFieldDeserializers[fieldIndex];fieldInfo = fieldDeserializer.fieldInfo;fieldClass = fieldInfo.fieldClass;fieldAnnotation = fieldInfo.getAnnotation();if (fieldAnnotation != null && fieldDeserializer instanceof DefaultFieldDeserializer) {customDeserializer = ((DefaultFieldDeserializer) fieldDeserializer).customDeserilizer;}}Object fieldValue = null;if (fieldDeserializer != null) {char[] name_chars = fieldInfo.name_chars;//指定了自定义发序列化器,后续使用自定义序列化器处理if (customDeserializer && lexer.matchField(name_chars)) {matchField = true;// 基本类型快速路径匹配} else if (fieldClass == int.class || fieldClass == Integer.class) {//词法分析,解析int值int intVal = lexer.scanFieldInt(name_chars);if (intVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {fieldValue = null;} else {fieldValue = intVal;}if (lexer.matchStat > 0) {matchField = true;valueParsed = true;} else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {//增加计算,记录未命中次数以调整匹配策略notMatchCount++;continue;}} else if(...){//省略其他基础类型处理}}// 快速匹配失败,动态扫描字段名,通过符号表优化:返回的字符串可能是符号表中的缓存实例if (!matchField) {key = lexer.scanSymbol(parser.symbolTable);// $ref 引用处理if ("$ref" == key && context != null) {handleReferenceResolution(lexer, parser, context)}// @type 类型处理if ((typeKey != null && typeKey.equals(key))|| JSON.DEFAULT_TYPE_KEY == key) {//AutoType安全检查config.checkAutoType(typeName, expectClass, lexer.getFeatures());handleTypeNameResolution(lexer, parser, config, beanInfo, type, fieldName);}}}// 5.如果对象为空,则创建对象实例if (object == null && fieldInfo == null) {object = createInstance(parser, type);if (object == null) {return null;}}//6. 字段值设置for (Map.Entry<String, Object> entry : fieldValues.entrySet()) {FieldDeserializer fieldDeserializer = getFieldDeserializer(entry.getKey());if (fieldDeserializer != null) {fieldDeserializer.setValue(object, entry.getValue());}}return (T) object;}
类型安全检查(AutoType检查)ParserConfig.java 中的checkAutoType方法对反序列化类型做黑白名单检查。public int scanFieldInt(char[] fieldName) {matchStat = UNKNOWN;// 1. 字段名匹配阶段if (!charArrayCompare(fieldName)) {matchStat = NOT_MATCH_NAME;return 0;}int offset = fieldName.length;char chLocal = charAt(bp + (offset++));// 2. 负号处理final boolean negative = chLocal == '-';if (negative) {chLocal = charAt(bp + (offset++));}// 3. 数字解析核心算法int value;if (chLocal >= '0' && chLocal <= '9') {value = chLocal - '0';for (;;) {chLocal = charAt(bp + (offset++));if (chLocal >= '0' && chLocal <= '9') {value = value * 10 + (chLocal - '0');// 十进制累加} else if (chLocal == '.') {matchStat = NOT_MATCH; // 拒绝浮点数return 0;} else {break;}}// 4. 溢出检测if (value < 0 //|| offset > 11 + 3 + fieldName.length) {if (value != Integer.MIN_VALUE //|| offset != 17 //|| !negative) {matchStat = NOT_MATCH;return 0;}}} else {matchStat = NOT_MATCH;return 0;}// 5. JSON 结束符处理if (chLocal == ',') {bp += offset;this.ch = this.charAt(bp);matchStat = VALUE;token = JSONToken.COMMA;return negative ? -value : value;}if (chLocal == '}') {// ... 处理对象结束和嵌套结构chLocal = charAt(bp + (offset++));if (chLocal == ',') {token = JSONToken.COMMA;bp += offset;this.ch = this.charAt(bp);} else if (chLocal == ']') {token = JSONToken.RBRACKET;bp += offset;this.ch = this.charAt(bp);} else if (chLocal == '}') {token = JSONToken.RBRACE;bp += offset;this.ch = this.charAt(bp);} else if (chLocal == EOI) {token = JSONToken.EOF;bp += (offset - 1);ch = EOI;} else {matchStat = NOT_MATCH;return 0;}matchStat = END;} else {matchStat = NOT_MATCH;return 0;}return negative ? -value : value;}
对象实例化过程JavaBeanDeserializer.java中的createInstance方法创建对象实例:// ParserConfig.java - AutoType安全检查public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features) {if (typeName == null) {return null;}if (typeName.length() >= 192 || typeName.length() < 3) {throw new JSONException("autoType is not support. " + typeName);}String className = typeName.replace('$', '.');Class<?> clazz = null;final long BASIC = 0xcbf29ce484222325L;final long PRIME = 0x100000001b3L;final long h1 = (BASIC ^ className.charAt(0)) * PRIME;// hash code编码匹配性能优化if (h1 == 0xaf64164c86024f1aL) {throw new JSONException("autoType is not support. " + typeName);}if ((h1 ^ className.charAt(className.length() - 1)) * PRIME == 0x9198507b5af98f0L) {throw new JSONException("autoType is not support. " + typeName);}final long h3 = (((((BASIC ^ className.charAt(0))* PRIME)^ className.charAt(1))* PRIME)^ className.charAt(2))* PRIME;if (autoTypeSupport || expectClass != null) {long hash = h3;for (int i = 3; i < className.length(); ++i) {hash ^= className.charAt(i);hash *= PRIME;if (Arrays.binarySearch(denyHashCodes, hash) >= 0 && TypeUtils.getClassFromMapping(typeName) == null) {throw new JSONException("autoType is not support. " + typeName);}if (Arrays.binarySearch(acceptHashCodes, hash) >= 0) {clazz = TypeUtils.loadClass(typeName, defaultClassLoader, false);if (clazz != null) {return clazz;}}}}// ... 更多安全检查逻辑return clazz;}
FieldDeserializer.java中的setValue方法通过反射实现字段设置:// JavaBeanDeserializer.java - 对象实例化protected Object createInstance(DefaultJSONParser parser, Type type) {if (type instanceof Class) {if (clazz.isInterface()) {// 接口类型使用Java反射创建实例Class<?> clazz = (Class<?>) type;ClassLoader loader = Thread.currentThread().getContextClassLoader();final JSONObject obj = new JSONObject();Object proxy = Proxy.newProxyInstance(loader, new Class<?>[] { clazz }, obj);return proxy;}}if (beanInfo.defaultConstructor == null && beanInfo.factoryMethod == null) {return null;}Object object;try {//通过构造器创建实例Constructor<?> constructor = beanInfo.defaultConstructor;if (beanInfo.defaultConstructorParameterSize == 0) {object = constructor.newInstance();} else {ParseContext context = parser.getContext();if (context == null || context.object == null) {throw new JSONException("can't create non-static inner class instance.");}final Class<?> enclosingClass = constructor.getDeclaringClass().getEnclosingClass();object = constructor.newInstance(context.object);}} catch (JSONException e) {throw e;} catch (Exception e) {throw new JSONException("create instance error, class " + clazz.getName(), e);}return object;}
// FieldDeserializer.java - 属性赋值的核心实现public void setValue(Objectobject, Object value) {if (value == null && fieldInfo.fieldClass.isPrimitive()) {return;} else if (fieldInfo.fieldClass == String.class&& fieldInfo.format != null&& fieldInfo.format.equals("trim")) {value = ((String) value).trim();}try {Method method = fieldInfo.method;if (method != null) {if (fieldInfo.getOnly) {// 处理只读属性的特殊情况if (fieldInfo.fieldClass == AtomicInteger.class) {AtomicInteger atomic = (AtomicInteger) method.invoke(object);if (atomic != null) {atomic.set(((AtomicInteger) value).get());}} else if (Map.class.isAssignableFrom(method.getReturnType())) {Map map = (Map) method.invoke(object);if (map != null) {map.putAll((Map) value);}} else {Collection collection = (Collection) method.invoke(object);if (collection != null && value != null) {collection.clear();collection.addAll((Collection) value);}}} else {// 通过setter方法赋值method.invoke(object, value);}} else {// 通过字段直接赋值final Field field = fieldInfo.field;if (field != null) {field.set(object, value);}}} catch (Exception e) {throw new JSONException("set property error, " + clazz.getName() + "#" + fieldInfo.name, e);}}
interface Animal {}class Dog implements Animal {private String name;private double weight;//省略getter,setter}class PetStore {private Animal animal;}public static void main(String[] args) {Animal dog = new Dog("dodi", 12);PetStore store = new PetStore(dog);String jsonString = JSON.toJSONString(store);PetStore petStore = JSON.parseObject(jsonString, PetStore.class);Dog parsedDog = (Dog) petStore.getAnimal();}
AutoType 让 fastjson 在反序列化时根据 @type 字段动态加载任意类,这一“便利”却成为攻击者远程代码执行的快捷通道:通过把JdbcRowSetImpl等 JNDI 敏感类写进 JSON,服务端在调用 setter 的瞬间就会向外部 LDAP/RMI 服务器拉取恶意字节码,完成 RCE;而官方长期依赖“黑名单”堵漏,导致 1.2.25→1.2.80 出现 L 描述符、Throwable 二次反序列化、内部类等连续绕过,形成“补丁-绕过-再补丁”的猫鼠游戏, 虽然在1.2.68 引入 safeMode 但为了兼容性需要使用者手动开启 ,而且实现也不够健壮,开启safeMode仍有利用代码漏洞绕过检查风险,后续版本对safeMode加固并对已知安全漏洞清零,直到最新1.2.83版本安全问题也不能说彻底解决。public static void main(String[] args) {Animal dog = new Dog("dodi", 12);PetStore store = new PetStore(dog);String jsonString = JSON.toJSONString(store, SerializerFeature.WriteClassName);PetStore petStore = JSON.parseObject(jsonString, PetStore.class);Dog parsedDog = (Dog) petStore.getAnimal();}
// 依赖:com.alibaba:fastjson:1.2.83try (JSONReader reader = new JSONReader(new InputStreamReader(new FileInputStream("huge-array.json"), StandardCharsets.UTF_8))) {reader.startArray(); // 告诉解析器:根节点是 []while (reader.hasNext()) { // 拉取下一条Order order = reader.readObject(Order.class); // 瞬时对象processOrder(order);//业务处理orderRepository.save(order); // 立即落盘,内存即可回收}reader.endArray();}
FASTJSON 2 Autotype机制介绍(https://alibaba.github.io/fastjson2/autotype_cn.html)
AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。
鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑