Fastjson1 处理额外 / 未知属性
在 Java 开发中,我们经常需要解析 JSON 数据。有时,JSON 中包含的字段比我们定义的 Java 类多,这些多余的字段被称为“额外属性”或“未知属性”。如果处理不当,程序可能会抛出异常或忽略重要数据。本文将为你介绍如何使用 Fastjson1 优雅地处理这些未知属性。
为什么需要处理未知属性?
假设我们有一个简单的 User 类:
public class User {
private String name;
private int age;
// getter/setter 省略
}
现在收到的 JSON 数据如下:
{
"name": "Alice",
"age": 25,
"email": "[email protected]",
"address": "123 Main St"
}
email 和 address 是 User 类中没有的属性。默认情况下,Fastjson 会忽略它们,不会报错。但有时我们需要保留这些额外信息,或者至少知道它们的存在。
1 忽略未知属性(默认行为)
Fastjson 默认会忽略未知属性,不会抛出异常。这是最简单的方式:
String json = "{\"name\":\"Alice\",\"age\":25,\"email\":\"[email protected]\"}";
User user = JSON.parseObject(json, User.class);
System.out.println(user.getName()); // 输出: Alice
System.out.println(user.getAge()); // 输出: 25
// email 被自动忽略
2 使用 @JSONField 注解
如果我们想保留某些额外字段,可以在类中使用 @JSONField 注解指定字段名:
public class User {
private String name;
private int age;
@JSONField(name = "email")
private String email;
// getter/setter 省略
}
这样,当 JSON 中包含 email 字段时,它会被映射到 email 属性。
3 使用 parseObject 参数
JSON.parseObject 可以接受一个额外的 Feature 参数来控制行为,它使用的是第二个参数:
import com.alibaba.fastjson.parser.Feature;
String json = "{\"name\":\"Alice\",\"age\":25,\"email\":\"[email protected]\"}";
// 默认行为:忽略未知字段
User user = JSON.parseObject(json, User.class, Feature.IgnoreNotMatch);
4 捕获所有未知属性(推荐)
有时我们需要捕获所有额外属性,例如用于日志记录或动态处理。可以使用 @JSONField 配合 Map 类型字段:
public class User {
private String name;
private int age;
@JSONField(deserializeUsing = ExtraProcessor.class)
private Map<String, Object> extraFields = new HashMap<>();
// getter/setter
}
但更常用的方法是覆盖 JSONObject 的 parseObject 行为。Fastjson 提供了 ExtraProcessor 接口:
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
User user = JSON.parseObject(json, User.class, new ExtraProcessor() {
@Override
public void processExtra(Object object, String key, Object value) {
System.out.println("发现额外字段: " + key + " = " + value);
// 可以存储到 Map 或其他地方
}
});
更优雅的方式是让类实现 ExtraProcessor 接口:
public class User implements ExtraProcessor {
private String name;
private int age;
private Map<String, Object> extraFields = new HashMap<>();
@Override
public void processExtra(Object object, String key, Object value) {
extraFields.put(key, value);
}
// getter/setter 省略
}
使用方式:
User user = JSON.parseObject(json, User.class);
System.out.println(user.getExtraFields()); // 输出: {[email protected], address=123 Main St}
实际应用场景
- API 网关:接收第三方数据时,某些字段可能是动态的。
- 日志记录:记录所有收到的字段以便调试。
- 版本兼容:新旧 API 字段不同时保持兼容。
完整示例
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import java.util.*;
public class ExtraFieldDemo {
public static void main(String[] args) {
String json = "{\"name\":\"Bob\",\"age\":30,\"job\":\"engineer\",\"hobby\":\"reading\"}";
// 使用匿名内部类
User user = JSON.parseObject(json, User.class, new ExtraProcessor() {
@Override
public void processExtra(Object object, String key, Object value) {
((User)object).getExtraFields().put(key, value);
}
});
System.out.println("Name: " + user.getName());
System.out.println("Extra fields: " + user.getExtraFields());
}
}
class User {
private String name;
private int age;
private Map<String, Object> extraFields = new HashMap<>();
// getter/setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Map<String, Object> getExtraFields() { return extraFields; }
public void setExtraFields(Map<String, Object> extraFields) { this.extraFields = extraFields; }
}
总结
处理 JSON 中的未知属性是日常开发中的常见需求。Fastjson1 提供了多种方式来处理:默认忽略、注解映射、特性控制以及 ExtraProcessor 接口。对于需要保留额外信息的情况,推荐使用 ExtraProcessor 方案,它既灵活又易于维护。

