序列化 之 fastJson(二)高级功能
Fastjson(尤其是 Fastjson 2.x,包名为 com.alibaba.fastjson2)除了基础的序列化/反序列化外,还提供了大量高级 API,用于处理复杂场景,如:
- 流式解析(避免内存溢出)
- 自定义类型转换
- 字段过滤与动态控制
- JSONPath 查询
- 与 Spring MVC 集成
- 性能调优与缓存机制
本文将系统讲解 Fastjson 的高级用法与 API 示例,以 Fastjson 2.0+ 为主(兼顾 1.x 差异说明)。
一、流式解析(Streaming Parse)—— 处理大 JSON 文件
当 JSON 数据非常大(如 1GB 日志文件),一次性加载到内存会 OOM。Fastjson 提供 JSONReader 流式读取。
✅ 示例:逐条读取 JSON 数组中的对象
import com.alibaba.fastjson2.JSONReader;
import java.io.FileReader;
import java.io.IOException;
public class StreamingParseDemo {
public static void main(String[] args) throws IOException {
try (FileReader fileReader = new FileReader("users.json");
JSONReader reader = JSONReader.of(fileReader)) {
// 假设 users.json 是 [{"name":"A"},{"name":"B"},...]
reader.startArray(); // 开始数组
while (reader.hasNext()) {
User user = reader.read(User.class); // 逐个读取
System.out.println("User: " + user.name);
}
reader.endArray();
}
}
public static class User {
public String name;
}
}
💡 优势:内存占用恒定,适合大数据量处理。
二、JSONPath —— 快速提取 JSON 子数据
Fastjson 内置 JSONPath 支持,类似 XPath,用于查询 JSON。
✅ 基础语法示例
String json = """
{
"company": {
"name": "Alibaba",
"employees": [
{"id": 1, "name": "张三", "dept": "RD"},
{"id": 2, "name": "李四", "dept": "QA"}
]
}
}
""";
JSONObject obj = JSON.parseObject(json);
// 获取公司名
String companyName = JSONPath.eval(obj, "$.company.name"); // "Alibaba"
// 获取所有员工姓名
List<String> names = JSONPath.eval(obj, "$.company.employees[*].name"); // ["张三", "李四"]
// 条件查询:ID=1 的员工
List<?> emp = JSONPath.eval(obj, "$.company.employees[?(@.id == 1)]");
⚠️ 注意:
- Fastjson 2.x 中
JSONPath类位于com.alibaba.fastjson2.JSONPath - 支持复杂表达式:
$..name(递归查找所有 name)、$[0:2](切片)等
三、字段过滤(PropertyFilter / NameFilter)
在序列化时动态决定是否输出某个字段,常用于权限控制(如管理员可见密码,普通用户不可见)。
✅ 方式1:使用 NameFilter(重命名或跳过)
User user = new User("admin", "123456");
String json = JSON.toJSONString(user, new NameFilter() {
@Override
public String process(Object object, String name, Object value) {
if ("password".equals(name) && !"admin".equals(getCurrentUser())) {
return null; // 返回 null 表示跳过该字段
}
return name; // 返回原字段名
}
});
✅ 方式2:使用 PropertyFilter(更直观)
String json = JSON.toJSONString(user, new PropertyFilter() {
@Override
public boolean apply(Object source, String name, Object value) {
// 返回 true 表示保留,false 表示过滤
if ("password".equals(name)) {
return "admin".equals(getCurrentUser());
}
return true;
}
});
🔒 应用场景:同一接口对不同角色返回不同字段。
四、自定义类型转换(TypeAdapter / ObjectReader)
当 JSON 字段与 Java 类型不匹配时(如字符串 "true" 转 Boolean),可自定义转换逻辑。
✅ 示例:将任意字符串转 Boolean("1"/"true"/"yes" → true)
public class FlexibleBooleanReader implements ObjectReader<Boolean> {
@Override
public Boolean readObject(JSONReader reader, Type fieldType, Object fieldName, long features) {
String str = reader.readString();
if (str == null) return null;
str = str.trim().toLowerCase();
return "1".equals(str) || "true".equals(str) || "yes".equals(str);
}
}
// 使用
@JSONField(deserializeUsing = FlexibleBooleanReader.class)
public Boolean enabled;
✅ 全局注册(Fastjson 2.x)
// 创建自定义模块(Fastjson 2.x 推荐方式)
ObjectWriterProvider writerProvider = new ObjectWriterProvider();
ObjectReaderProvider readerProvider = new ObjectReaderProvider();
readerProvider.register(Boolean.class, FlexibleBooleanReader::new);
// 在 toJSONString 或 parseObject 时传入
JSON.toJSONString(obj,
JSONWriter.of(writerProvider, ...).getContext());
💡 更推荐在字段上用
@JSONField(deserializeUsing=...)局部控制。
五、与 Spring MVC 集成(替换 Jackson)
虽然 Spring Boot 默认用 Jackson,但可配置 Fastjson 作为 HTTP 消息转换器。
✅ 步骤(Spring Boot + Fastjson 2.x)
- 添加依赖
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension-spring6</artifactId> <!-- Spring 6 / Boot 3 -->
<!-- 或 fastjson2-extension-spring5 for Spring Boot 2.x -->
<version>2.0.57</version>
</dependency>
- 配置 WebMvcConfigurer
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setWriterFeatures(JSONWriter.Feature.PrettyFormat);
config.setReaderFeatures(JSONReader.Feature.IgnoreSetNullValue);
converter.setFastJsonConfig(config);
converter.setDefaultCharset(StandardCharsets.UTF_8);
// 支持 application/json
converter.setSupportedMediaTypes(Arrays.asList(
MediaType.APPLICATION_JSON,
MediaType.APPLICATION_JSON_UTF8
));
converters.add(0, converter); // 插入首位,优先使用
}
}
✅ 控制器中
@ResponseBody/@RequestBody自动使用 Fastjson。
六、性能优化技巧
1. 启用 ASM 优化(默认已开启)
Fastjson 2.x 默认使用字节码生成加速序列化。
2. 复用 JSONWriter / JSONReader
避免频繁创建解析器对象。
3. 关闭不必要的 Feature
如非必要,不要开启 WriteClassName、WriteMapNullValue 等。
4. 使用 toJSONBytes() 替代 toJSONString().getBytes()
减少字符串中间对象:
byte[] jsonBytes = JSON.toJSONBytes(user); // 直接输出 byte[]
七、高级注解详解
| 注解 | 说明 |
|---|---|
@JSONType(alphabetic = false) |
保持字段原始顺序(默认按字母排序) |
@JSONType(ignores = {"password"}) |
类级别忽略字段 |
@JSONField(unwrapped = true) |
展开嵌套对象字段(类似 Jackson 的 @JsonUnwrapped) |
@JSONField(label = "sensitive") |
配合 LabelFilter 实现标签过滤 |
✅ unwrapped 示例
public class Address {
public String city;
public String street;
}
public class User {
public String name;
@JSONField(unwrapped = true)
public Address addr;
}
// 序列化结果: {"name":"张三","city":"杭州","street":"文一西路"}
八、安全加固(必读!)
1. 禁用 AutoType(默认已禁用)
Fastjson 2.x 默认 不支持 @type,无需额外配置。
2. 如必须使用 AutoType,严格白名单
// Fastjson 1.x 方式(不推荐)
ParserConfig.getGlobalInstance().addAccept("com.yourcompany.model.");
// Fastjson 2.x 不建议开启,若需请使用 SafeMode
System.setProperty("fastjson2.parser.safeMode", "true");
3. 升级到最新版
定期关注 Fastjson GitHub 安全公告。
九、Fastjson 1.x 与 2.x 关键差异速查
| 功能 | Fastjson 1.x | Fastjson 2.x |
|---|---|---|
| 包名 | com.alibaba.fastjson |
com.alibaba.fastjson2 |
| 流式读取 | JSONReader |
JSONReader(API 更简洁) |
| JSONPath | com.alibaba.fastjson.JSONPath |
com.alibaba.fastjson2.JSONPath |
| Spring 集成 | FastJsonHttpMessageConverter |
fastjson2-extension-spring* |
| AutoType | 默认部分开启(危险) | 默认完全禁用(安全) |
| 性能 | 快 | 更快(重构 + ASM 优化) |
总结:Fastjson 高级能力全景
| 能力 | API / 方法 | 适用场景 |
|---|---|---|
| 流式解析 | JSONReader.of(inputStream) |
大文件处理 |
| JSONPath 查询 | JSONPath.eval(obj, "$.a.b") |
快速提取子数据 |
| 动态字段过滤 | PropertyFilter / NameFilter |
权限控制、脱敏 |
| 自定义类型转换 | ObjectReader / ObjectWriter |
非标准格式兼容 |
| Spring 集成 | FastJsonHttpMessageConverter |
替换 Jackson |
| 性能优化 | toJSONBytes()、ASM、Feature 调优 |
高并发服务 |
| 安全防护 | 禁用 AutoType、白名单 | 防 RCE 攻击 |
📌 建议:新项目优先考虑 Fastjson 2.x;若无特殊需求,也可选用 Jackson(生态更稳、漏洞少)。
本文来自博客园,作者:蓝迷梦,转载请注明原文链接:https://www.cnblogs.com/hewei-blogs/articles/19523400

浙公网安备 33010602011771号