FastJSON使用
一、概述
FastJSON是阿里巴巴开源的高性能JSON处理框架,以速度快、功能全、易用性强著称。本文将从核心注解@JSONField入手,详解对象与JSON的转换技巧、自定义过滤规则,并提供生产级工具类封装,帮助开发者高效处理JSON场景。
二、序列化与反序列化
fastjson支持多种方式定制序列化。
- 通过@JSONField定制序列化
- 通过@JSONType定制序列化
- 通过SerializeFilter定制序列化
- 通过ParseProcess定制反序列化
2.1 使用@JSONField配置
@JSONField是FastJSON最核心的字段级注解,可配置在字段、Getter/Setter方法上,精准控制单个字段的序列化/反序列化行为。
2.1.1 核心属性说明
package com.alibaba.fastjson.annotation;
public @interface JSONField {
// 序列化/反序列化顺序(1.1.42+版本支持),数值越小越靠前
int ordinal() default 0;
// JSON字段名映射(解决命名规范不一致问题)
String name() default "";
// 日期格式定制(仅对Date类型生效)
String format() default "";
// 是否参与序列化
boolean serialize() default true;
// 是否参与反序列化
boolean deserialize() default true;
// 自定义序列化器(1.2.16+版本支持)
Class<? extends ObjectSerializer> serializeUsing() default ObjectSerializer.class;
}
2.1.2 常见配置场景
(1)字段名映射与日期格式化
public class UserVO {
// 字段级配置:JSON字段名为ID,替代默认的userId
@JSONField(name = "ID")
private Integer userId;
private Date birthday;
// Getter方法级配置:日期格式统一为yyyy-MM-dd
@JSONField(name = "birthday", format = "yyyy-MM-dd")
public Date getBirthday() {
return birthday;
}
}
(2)排除指定字段序列化/反序列化
public class OrderVO {
// 不参与序列化(如敏感字段)
@JSONField(serialize = false)
private String tradePassword;
// 不参与反序列化(如仅用于展示的计算字段)
@JSONField(deserialize = false)
private BigDecimal totalAmount;
}
(3)指定字段序列化顺序
FastJSON默认按字段名字母序序列化,可通过ordinal自定义顺序(1.1.42+版本):
public class GoodsVO {
@JSONField(ordinal = 3)
private String goodsName; // 第3个输出
@JSONField(ordinal = 1)
private Long goodsId; // 第1个输出
@JSONField(ordinal = 2)
private Double price; // 第2个输出
}
(4)自定义字段序列化器
对特定字段定制序列化逻辑(如数值添加单位),需1.2.16+版本:
// 自定义序列化器:为数值添加"元"单位
public class AmountSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName,
Type fieldType, int features) throws IOException {
if (object == null) {
// 使用writeNull()确保输出JSON null而不是字符串"null"
serializer.writeNull();
return;
}
BigDecimal amount = (BigDecimal) object;
serializer.write(amount + "元");
}
}
// 业务类使用自定义序列化器
public class OrderVO {
@JSONField(serializeUsing = AmountSerializer.class)
private BigDecimal orderAmount;
}
// 测试验证
OrderVO order = new OrderVO();
order.setOrderAmount(new BigDecimal("100.00"));
String json = JSON.toJSONString(order);
// 输出:{"orderAmount":"100.00元"}
注意:若字段为私有属性,必须提供
Setter方法才能完成反序列化(FastJSON优先解析Getter/Setter,而非直接解析字段)。
2.2 使用@JSONType配置
@JSONType与@JSONField功能类似,但作用于整个类,适合统一配置类中所有字段的序列化规则(如全局日期格式、序列化顺序):
// 类级配置:所有日期字段默认格式yyyy-MM-dd HH:mm:ss,按字段声明顺序序列化
@JSONType(format = "yyyy-MM-dd HH:mm:ss", ordinal = true)
public class UserInfo {
private Long id;
private String name;
private Date createTime;
}
2.3 通过SerializeFilter定制序列化
SerializeFilter是扩展接口,支持通过代码动态定制序列化逻辑,核心类型如下:
| 过滤器类型 | 作用场景 | 核心方法 |
|---|---|---|
| PropertyPreFilter | 序列化前过滤字段(仅判断字段名, 避免 Getter调用异常) |
boolean apply(JSONSerializer serializer, Object object, String name) |
| PropertyFilter | 按字段名/字段值过滤字段 | boolean apply(Object object, String name, Object value) |
| NameFilter | 动态修改JSON字段名 |
String process(Object object, String name, Object value) |
| ValueFilter | 动态修改JSON字段值 |
Object process(Object object, String name, Object value) |
| BeforeFilter | 序列化时在字段最前添加自定义内容 | void writeBefore(Object object)(需调用writeKeyValue添加内容) |
| AfterFilter | 序列化时在字段最后添加自定义内容 | void writeAfter(Object object)(需调用writeKeyValue添加内容) |
示例1:按字段值过滤序列化
// 仅序列化id≥100的字段
PropertyFilter filter = (source, name, value) -> {
if ("id".equals(name)) {
return ((Integer) value) >= 100;
}
return true; // 其他字段正常序列化
};
UserVO user = new UserVO();
user.setUserId(101);
user.setName("张三");
String json = JSON.toJSONString(user, filter);
// 输出:{"ID":101,"name":"张三"}(id=101满足条件)
示例2:动态修改JSON字段名(下划线转驼峰)
NameFilter nameFilter = (object, name, value) ->
// 字段名转下划线格式(如createTime→create_time)
CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name);
String json = JSON.toJSONString(user, nameFilter);
// 输出:{"id":101,"create_time":"2025-12-03"}
示例3:AfterFilter序列化时追加自定义字段
AfterFilter用于在对象原有字段序列化完成后,追加自定义的JSON键值对,适用于统一添加扩展字段(如数据版本、序列化时间等)。
// 自定义AfterFilter:在序列化结果末尾添加扩展字段
AfterFilter afterFilter = new AfterFilter() {
@Override
public void writeAfter(Object object) {
// 为所有序列化对象添加序列化时间和数据版本号
this.writeKeyValue("serialize_time", System.currentTimeMillis());
this.writeKeyValue("data_version", "v1.0");
// 针对特定类型对象追加专属字段
if (object instanceof UserVO) {
UserVO user = (UserVO) object;
this.writeKeyValue("user_type", user.getUserId() > 100 ? "VIP" : "NORMAL");
}
}
};
// 测试使用AfterFilter
UserVO user = new UserVO();
user.setUserId(101);
user.setBirthday(new Date());
String json = JSON.toJSONString(user, afterFilter);
// 输出结果示例:
// {
// "ID":101,
// "birthday":"2025-12-03",
// "serialize_time":1733228967890,
// "data_version":"v1.0",
// "user_type":"VIP"
// }
2.4 通过ParseProcess定制反序列化
ParseProcess用于处理反序列化时的特殊场景(如多余字段、类型转换),核心实现类:
2.4.1 使用ExtraProcessor处理多余字段
public class OrderExtraProcessor implements ExtraProcessor {
@Override
public void processExtra(Object object, String key, Object value) {
// 将JSON中多余的字段存入Order的attributes属性
OrderVO order = (OrderVO) object;
order.getAttributes().put(key, value);
}
}
// 反序列化时传入处理器
String json = "{\"id\":123,\"name\":\"测试订单\",\"status\":\"SUCCESS\"}";
OrderVO order = JSON.parseObject(json, OrderVO.class, new OrderExtraProcessor());
// 多余的status字段会被存入attributes Map中
2.4.2 使用ExtraTypeProvider为多余的字段提供类型
public class OrderTypeProvider implements ExtraTypeProvider {
@Override
public Type getExtraType(Object object, String key) {
// 为value字段指定Integer类型(JSON中为字符串也能正确转换)
if ("value".equals(key)) {
return Integer.class;
}
return null; // 其他字段使用默认类型
}
}
// 组合使用:处理多余字段+指定类型
String json = "{\"id\":123,\"value\":\"1000\"}";
OrderVO order = JSON.parseObject(json, OrderVO.class,
new OrderExtraProcessor(), new OrderTypeProvider());
// value字段会被解析为Integer类型,而非String
三、Java对象↔JSON字符串
FastJSON提供JSON工具类,支持一键完成对象与JSON的转换,涵盖单个对象、集合、数组等场景。
3.1 Java对象→JSON字符串
基础用法:JSON.toJSONString()
public class test {
public static List<Person> init(){
List<Person> personList = new ArrayList<Person>();
personList.add(new Person(15, "John", "Doe", new Date()));
personList.add(new Person(20, "Janette", "Doe", new Date()));
return personList;
}
@Test
public void toJsonString() {
List<Person> personList = initPersons();
// 基础序列化(按 @JSONField 配置输出)
String json = JSON.toJSONString(personList);
System.out.println(json);
}
}
输出结果为:
[{
"age":"15",
"firstName":"Doe",
"lastName":"Jhon",
"dateOfBirth":"19/07/2016"
},{
"age":"20",
"firstName":"Doe",
"lastName":"Janette",
"dateOfBirth":"19/07/2016"
}]
进阶用法:BeanToArray序列化(转为数组格式)
String jsonOutput= JSON.toJSONString(listOfPersons, SerializerFeature.BeanToArray);
输出结果为:
[[
15,
1469003271063,
"John",
"Doe"
],[
20,
1469003271063,
"Janette",
"Doe"
]]
3.2 JSON字符串→Java对象
单个对象:JSON.parseObject()
public class test {
@Test
public void toJsonString() {
String json = "{\"firstName\":\"Doe\",\"lastName\":\"John\",\"dateOfBirth\":\"19/07/2024\"}";
// JSON 字符串 → Person 对象(自动匹配 @JSONField 配置)
Person person = JSON.parseObject(json, Person.class);
System.out.println(person);
}
}
集合对象:JSON.parseArray()
public class test {
@Test
public void toJsonString() {
String json = "[{\"firstName\":\"Doe\"},{\"firstName\":\"Janette\"}]";
// JSON 数组 → List<Person>
List<Person> personList = JSON.parseArray(json, Person.class);
System.out.println(personList.size()); // 输出 2
}
}
反序列化注意事项:
- 若
JavaBean无默认无参构造函数,必须用@JSONCreator注解指定构造函数(如本文开头的Person类);- 若
JSON字段与Java字段名一致(未用name配置),FastJSON会自动映射;- 日期字段需确保
JSON格式与format配置一致,否则会反序列化失败。
四、创建JSON对象
创建JSON对象非常简单,只需使用JSONObject(fastJson提供的json对象)和JSONArray(fastJson提供json数组对象)对象即可。
我们可以把JSONObject当成一个Map<String, Object>来看,只是JSONObject提供了更为丰富便捷的方法,方便我们对于对象属性的操作。我们看一下源码。
public class JSONObject extends JSON implements Map<String, Object>, Cloneable,
Serializable, InvocationHandler {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
private final Map<String, Object> map;
//...
}
同样我们可以把JSONArray当做一个List<Object>,也可以把JSONArray看成JSONObject对象的一个集合。
public class JSONArray extends JSON implements List<Object>, Cloneable, RandomAccess, Serializable {
private static final long serialVersionUID = 1L;
private final List<Object> list;
protected transient Object relatedArray;
protected transient Type componentType;
//...
}
此外,由于JSONObject和JSONArray继承了JSON,所以说也可以直接使用两者对JSON格式字符串与JSON对象及javaBean之间做转换,不过为了避免混淆我们还是使用JSON。
@Test
public void createJsonArray() throws ParseException {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < 2; i++) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("age", 10);
jsonObject.put("firstName", "Doe " + i);
jsonObject.put("dateOfBirth", "2016/12/12 12:12:12");
jsonArray.add(jsonObject);
}
String jsonOutput = jsonArray.toJSONString();
}
输出结果为:
[{
"age":"10",
"dateOfBirth":"2016/12/12 12:12:12",
"firstName":"Doe 0"
},{
"age":"10",
"dateOfBirth":"2016/12/12 12:12:12",
"firstName":"Doe 1"
}]
五、高级使用
5.1 使用ContextValueFilter配置JSON转换
在某些场景下,对Value做过滤,需要获得所属JavaBean的信息,包括类型、字段、方法等。在fastjson-1.2.9中,提供了ContextValueFilter,类似于之前版本提供的ValueFilter,只是多了BeanContext参数可用。
@Test
public void testContextValueFilter() {
ContextValueFilter valueFilter = new ContextValueFilter () {
public Object process(BeanContext context, Object object, String name, Object value) {
if (name.equals("dateOfBirth")) {
return "NOT TO DISCLOSE";
}
if (value.equals("John")) {
return ((String) value).toUpperCase();
} else {
return null;
}
}
};
String jsonOutput = JSON.toJSONString(listOfPersons, valueFilter);
}
以上实例中我们隐藏了dateOfBirth字段,并过滤名字不包含John的字段:
[{
"FIRSTNAME":"JOHN",
"LASTNAME":"DOE",
"dateOfBirth":"NOT TO DISCLOSE"
}]
5.2 使用SerializeConfig全局序列化配置
SerializeConfig:用于配置特定类型的序列化规则(如全局日期格式、自定义序列化器):
@Test
public void testSerializeConfig() {
// 1. 创建全局配置
SerializeConfig config = new SerializeConfig();
// 配置 Date 类型全局格式化
config.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
// 2. 应用配置序列化
String json = JSON.toJSONString(initPersons(), config);
System.out.println(json);
}
输出结果(日期格式统一为yyyy-MM-dd HH:mm:ss):
[{
"firstName": "Doe",
"lastName": "John",
"dateOfBirth": "2024-07-19 15:30:00"
}]
工具类封装FastJsonUtils
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.JSONLibDataFormatSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class FastJsonUtils extends JSON implements Serializable {
private static final SerializeConfig config;
static {
config = new SerializeConfig();
// 使用和json-lib兼容的日期输出格式
config.put(java.util.Date.class, new JSONLibDataFormatSerializer());
// 使用和json-lib兼容的日期输出格式
config.put(java.sql.Date.class, new JSONLibDataFormatSerializer());
}
/**
* 输出空置字段
*/
private static final SerializerFeature[] features = {SerializerFeature.WriteMapNullValue,
// list字段如果为null,输出为[],而不是null
SerializerFeature.WriteNullListAsEmpty,
// 数值字段如果为null,输出为0,而不是null
//SerializerFeature.WriteNullNumberAsZero,
// Boolean字段如果为null,输出为false,而不是null
SerializerFeature.WriteNullBooleanAsFalse,
// 字符类型字段如果为null,输出为"",而不是null
SerializerFeature.WriteNullStringAsEmpty
};
public static JSONObject getJson() {
return new JSONObject();
}
public static JSONArray getJsonArray() {
return new JSONArray();
}
/**
* 类转json字符串 时间复杂化处理,并且会打印空属性
*
* @param object
* @return {"firstName":"Doe","lastName":"John","dateOfBirth":"19/09/2021"}
*/
public static String objToJsonStrWithCF(Object object) {
return JSON.toJSONString(object, config, features);
}
/**
* 类转json字符串
* 时间复杂化处理,空属性不会打印
*
* @param object
* @return {"firstName":"Doe","lastName":"John","dateOfBirth":"19/09/2021"}
*/
public static String objToJsonStrWithC(Object object) {
return JSON.toJSONString(object, config);
}
/**
* 类转json字符串
* 会打印对象中所有的属性,没值的直接为空
*
* @param object
* @return {"firstName":"Doe","lastName":"John","dateOfBirth":"19/09/2021"}
*/
public static String objToJsonStrWithF(Object object) {
return JSON.toJSONString(object, features);
}
/**
* 类转json字符串
* 会打印对象中所有的属性,没值的直接为空
*
* @param object
* @return {"firstName":"Doe","lastName":"John","dateOfBirth":"19/09/2021"}
*/
public static String objToJsonStr(Object object) {
return JSON.toJSONString(object);
}
/**
* 推荐使用
* 类转json字符串 只打印对象中有值的,没有值的不打印
*
* @param object
* @return
*/
public static String obj2JsonStr(Object object) {
ParserConfig.getGlobalInstance().setAsmEnable(false);
return JSON.toJSONString(object, features);
}
/**
* json字符串转为object类
*
* @param text
* @return
*/
public static Object strToBean(String text) {
return JSON.parse(text);
}
/**
* json字符串转bean
* 注意:部分格式转换可能有错误
* -- 比如:日期 dd/MM/yyyy格式 转换成javaBean会出错
*
* @param text
* @param clazz
* @param <T>
* @return
*/
public static <T> T strToBean(String text, Class<T> clazz) {
return JSON.parseObject(text, clazz);
}
/**
* 将string转化为序列化的json字符串
*
* @return
*/
public static Object strToJson(String text) {
return JSON.parse(text);
}
/**
* str转json
* @param text
* @return
*/
public static JSONObject str2Json(String text) {
return JSONObject.parseObject(text);
}
/**
* str转json
* Feature.OrderedField防止乱序
* @param text
* @return
*/
public static JSONObject str2Json2(String text) {
return JSON.parseObject(text, Feature.OrderedField);
}
/**
* 转换JSON字符串为对象
*
* @param str
* @param clazz
* @return
*/
public static Object strToObject(String str, Class<?> clazz) {
return JSONObject.parseObject(str, clazz);
}
/**
* str转java 对象
* 注意:Class<T>需无参构造
*
* @param str
* @param tClass
* @param <T>
* @return
*/
public static <T> T getJavaObject(String str, Class<T> tClass) {
return JSON.toJavaObject(str2Json(str), tClass);
}
//-------------------------集合---------------------------------
/**
* 对象集合转json字符串
* @param list
* @param <T>
* @return
*/
public static <T> String listToJson(List<T> list) {
return JSON.toJSONString(list);
}
/**
* json字符串转为数组
*
* @param text
* @param <T>
* @return
*/
public static <T> Object[] strToArray(String text) {
return strToArray(text, null);
}
/**
* json字符串转为对象数组
*
* @param text
* @param clazz
* @param <T>
* @return
*/
public static <T> Object[] strToArray(String text, Class<T> clazz) {
return JSON.parseArray(text, clazz).toArray();
}
/**
* json字符串转为对象集合
*
* @param text
* @param clazz
* @param <T>
* @return
*/
public static <T> List<T> strToList(String text, Class<T> clazz) {
return JSON.parseArray(text, clazz);
}
/**
* json字符串转对象集合
* @param text
* @param clazz
* @param <T>
* @return
*/
public static <T> List<T> jsonToList(String text, Class<T> clazz) {
return JSONArray.parseArray(text, clazz);
}
/**
* json字符串转化为map
*
* @param str
* @return
*/
public static <K, V> Map<K, V> strToMap(String str) {
return JSON.parseObject(str, Map.class);
}
/**
* 将map转化为string
*
* @param map
* @return
*/
public static <K, V> String mapToStr(Map<K, V> map) {
return JSONObject.toJSONString(map);
}
/**
* JSON数组形式字符串转换为List<Map<String, String>>
* @param strArr
* @return
*/
public static List<Map<String, String>> strArrToListMap(String strArr) {
return JSON.parseObject(strArr, new TypeReference<List<Map<String, String>>>() {});
}
public static List<Person> initList() {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person(15, "John", "Doe", new Date()));
personList.add(new Person(20, "Janette", "Doe", new Date()));
return personList;
}
public static Person initJson() {
return new Person(15, null, "Doe", new Date());
}
public static void main(String[] args) {
Person person = initJson();
System.out.println("objToJsonStrWithCF:" + objToJsonStrWithCF(person));
System.out.println("objToJsonStrWithF:" + objToJsonStrWithF(person));
System.out.println("objToJsonStrWithC:" + objToJsonStrWithC(person));
System.out.println("objToJsonStr:" + objToJsonStr(person));
System.out.println("obj2JsonStr:" + obj2JsonStr(person));
String s = objToJsonStrWithCF(person);
System.out.println("strToBean:" + JSON.toJSONString(strToBean(s)));
System.out.println("strToBean:" + JSON.toJSONString(strToBean(s, Person.class)));
System.out.println("-------list-----------");
String jsonList = JSON.toJSONString(initList());
System.out.println("listToJson:" + JSON.toJSONString(listToJson(initList())));
System.out.println("strToArray:" + JSON.toJSONString(strToArray(jsonList)));
System.out.println("strToObject:" + strToObject(s, Person.class));
System.out.println("getJavaObject:" + getJavaObject(s, Person.class));
System.out.println("strToList:" + strToList(jsonList, Person.class));
System.out.println("jsonToList:" + JSON.toJSONString(jsonToList(JSON.toJSONString(strToArray(jsonList)), Person.class)));
System.out.println("------map-----------");
System.out.println("strToMap:" + strToMap(s));
System.out.println("mapToStr:" + mapToStr(strToMap(s)));
//objToJsonStrWithCF:{"age":15,"firstName":"Doe","lastName":"","dateOfBirth":"2021-09-19"}
//objToJsonStrWithF:{"age":15,"firstName":"Doe","lastName":"","dateOfBirth":"2021-09-19"}
//objToJsonStrWithC:{"age":15,"firstName":"Doe","dateOfBirth":"2021-09-19"}
//objToJsonStr:{"age":15,"firstName":"Doe","dateOfBirth":"2021-09-19"}
//obj2JsonStr:{"age":15,"firstName":"Doe","lastName":"","dateOfBirth":"2021-09-19"}
//strToBean:{"firstName":"Doe","lastName":"","dateOfBirth":"2021-09-19","age":15}
//strToBean:{"age":15,"firstName":"Doe","lastName":"","dateOfBirth":"2021-09-19"}
//-------list-----------
//listToJson:"[{\"age\":15,\"firstName\":\"Doe\",\"lastName\":\"John\",\"dateOfBirth\":\"2021-09-19\"},{\"age\":20,\"firstName\":\"Doe\",\"lastName\":\"Janette\",\"dateOfBirth\":\"2021-09-19\"}]"
//strToArray:[{"firstName":"Doe","lastName":"John","dateOfBirth":"2021-09-19","age":15},{"firstName":"Doe","lastName":"Janette","dateOfBirth":"2021-09-19","age":20}]
//strToObject:Person(age=15, lastName=, firstName=Doe, dateOfBirth=Sun Sep 19 00:00:00 CST 2021)
//getJavaObject:Person(age=15, lastName=, firstName=Doe, dateOfBirth=Sun Sep 19 00:00:00 CST 2021)
//strToList:[Person(age=15, lastName=John, firstName=Doe, dateOfBirth=Sun Sep 19 00:00:00 CST 2021), Person(age=20, lastName=Janette, firstName=Doe, dateOfBirth=Sun Sep 19 00:00:00 CST 2021)]
//jsonToList:[{"age":15,"firstName":"Doe","lastName":"John","dateOfBirth":"2021-09-19"},{"age":20,"firstName":"Doe","lastName":"Janette","dateOfBirth":"2021-09-19"}]
//------map-----------
//strToMap:{"firstName":"Doe","lastName":"","dateOfBirth":"2021-09-19","age":15}
//mapToStr:{"firstName":"Doe","lastName":"","dateOfBirth":"2021-09-19","age":15}
}
}

浙公网安备 33010602011771号