** fastjson 版本: 1.2.36 **
主要 API
序列化 API (String JSON.toJSONString(Object …)) : 将对象序列化为 json 字符串
反序列化 API (T JSON.parseObject(String str, …)) 将 json 字符串序列化为对象.
JSON.toJSONString(Object …)
有多个重载方法,不同的参数对序列化过程进行控制。可以看到,主要是通过三个参数来对序列化进行干预的,SerializeConfig
这是序列化全局配置, SerializeFilter
序列化过滤器,SerializeFeature
这是fastjson自定义的特征枚举变量,定制序列化过程。
SerializeFeature
为什么先说这个,因为这个应用范围最广,能够覆盖大部分的序列化要求。
这是一个枚举类,列举了一系列序列化的参数。
package com.alibaba.fastjson.serializer;
/**
*
*/
public enum SerializerFeature {
QuoteFieldNames, // 输出 Key 时是否使用双引号, 默认 true
UseSingleQuotes, // 输出key时使用单引号而不是双引号, 默认 false
WriteMapNullValue, // 是否输出值为 null 的字段, 默认 false, 默认不输出值为 null 的字段
WriteEnumUsingToString, // Enum 输出其toString() 值,可以重写 toString 来自定义输出形式,但是这样做会带来一个问题,对应的反序列化使用的Enum的静态方法valueof可能无法识别自行生成的toString(),导致反序列化出错
WriteEnumUsingName, // Enum 输出其name() 值,默认 true, 如果需要序列化其 ordinal() 值, 禁用掉该选项,如何禁用具体代码见后文
UseISO8601DateFormat, // Date使用ISO8601格式输出,默认为 false
WriteNullListAsEmpty, // List 字段如果为 null,输出 [] 而不是 null,默认 false
WriteNullStringAsEmpty, // String 字段如果为 null, 输出 "",而不是 null,默认 false
WriteNullNumberAsZero, // 数值字段如果为 null, 输出0而不是null,默认 false
WriteNullBooleanAsFalse, // Boolean字段如果为 null, 输出 false而不是 null,默认 false
SkipTransientField, // 字段如果加了@Transient 注解,则不序列化该字段, 默认 true
SortField, // 按字段名称排序后输出, 默认 true, 会按字段名称字母排序。
/** @deprecated */
@Deprecated
WriteTabAsSpecial,
PrettyFormat, // 是否格式化输出
WriteClassName, // 序列化时写入类型信息,默认 false。反序列化时需用到
DisableCircularReferenceDetect, //消除对同一对象循环引用的问题,默认 false
WriteSlashAsSpecial, // 对斜杠 / 进行转义, 转义成 \/
BrowserCompatible,
WriteDateUseDateFormat, // 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
NotWriteRootClassName,
/** @deprecated */
DisableCheckSpecialChar, //一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false
BeanToArray,
WriteNonStringKeyAsString,
NotWriteDefaultValue, // 不写入默认值, 默认 false
BrowserSecure,
IgnoreNonFieldGetter, // 忽略不是类字段对应的getter 方法 ,默认 false
WriteNonStringValueAsString,
IgnoreErrorGetter,
WriteBigDecimalAsPlain,
MapSortField;
}
还是举例说明吧
以老掉牙的 User 类举例
public class User {
private String name;
private String sex;
private String address;
private String defVal = "hello"; // 有默认值
private String trans; // get 方法加了@Transient 注解
private int age;
private Long seconds;
private BigDecimal salary;
private Boolean flag;
private Date birth;
private List<String> roles;
private Map<String,Object> map;
private Week week;
private String nullVal;
public enum Week {
Mon(1), Tue(2), Wed(3), Thu(4), Fir(5), Sat(6), Sun(7);
private int val;
Week(Integer val) {
this.val = val;
}
public int getVal() {
return val;
}
}
// 这是额外定义的getTest()方法,类中并没有 test 字段。
public String getTest() {
return "test";
}
@Transient
public String getTrans() {
return trans;
}
public void setTrans(String trans) {
this.trans = trans;
}
...
其余 getter/setter 方法
基础序列化;
@Test
public void test() {
User user = new User();
user.setName("张三");
user.setAge(12);
user.setSex("1");
user.setAddress("杭州123号\t\n\r \"京城18号\"");
user.setWeek(User.Week.Fir);
String userStr = JSON.toJSONString(user);
System.out.println(userStr);
}
输出结果:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
User类的 seconds, roles, nullVal 等值为 null 的字段没有输出来,说明默认情况下值为 null 的字段是不序列化的。defVal 在定义的初始化为hello,也是输出了的。另外额外定义的getTest方法,fastjson就会序列化test字段出来,哪怕类中没有 test Field。可以用 SerializeFeature.IgnoreNonFieldGetter 忽略掉这些不是Field 字段的 getter 方法。
WriteMapNullValue 是否输出值为 null 的字段
因为fastjson默认是不序列化值为 null 的字段的,加了这个选项,那么值为 null 的字段也会输出。
String userStr = JSON.toJSONString(user, SerializerFeature.WriteMapNullValue);
System.out.println(userStr);
输出结果:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"birth":null,"defVal":"hello","flag":null,"map":null,"name":"张三","nullVal":null,"roles":null,"salary":null,"seconds":null,"sex":"1","test":"test","week":"Fir"}
值为 null 的 字段也输出了。
WriteNullListAsEmpty, WriteNullStringAsEmpty,,WriteNullNumberAsZero,WriteNullBooleanAsFalse
直接上代码,具体含义上面也说了。
String userStr = JSON.toJSONString(user, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullBooleanAsFalse);
// 另外也可以这么写: String userStr = JSON.toJSONString(user, SerializerFeature.WRITE_MAP_NULL_FEATURES);
WRITE_MAP_NULL_FEATURES 相当于这四个特性。
System.out.println(userStr);
输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"birth":null,"defVal":"hello","flag":false,"map":null,"name":"张三","nullVal":"","roles":[],"salary":0,"seconds":0,"sex":"1","test":"test","week":"Fir"}
可以看到roles序列化化为 [], salay序列化为 0,flag 序列化为false, nullVal序列化为 “” (空字符串),
WriteEnumUsingToString 和 WriteEnumUsingName
WriteEnumUsingToString 会使用 enum 的 toString() 返回值来序列化枚举类型。例如在上例中,我们在enum Week 中重写 toString() 方法。因为enum默认的 toString 方法就是输出其 name 值,如果不重写 toString() 方法,其输出就是其 name 值
public enum Week {
Mon(1), Tue(2), Wed(3), Thu(4), Fir(5), Sat(6), Sun(7);
private int val;
Week(Integer val) {
this.val = val;
}
public int getVal() {
return val;
}
@Override
public String toString() {
return this.ordinal() + ":" + this.name();
}
}
String userStr = JSON.toJSONString(user, SerializerFeature.WriteEnumUsingToString);
输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"4:Fir"}
week字段的输出变成了 『4:Fir』
WriteEnumUsingName 默认为 true, fastjson 默认输出枚举类型的 name 值,如果想要输出其 ordinal 值, 将其值设置为 false 即可。怎么设置呢,这里就要用到SerializeFeature 的 config 方法了。看代码
int feature = SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteEnumUsingName, false);
String userStr = JSON.toJSONString(user, feature);
System.out.println(userStr);
输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":4}
week值变成了4, ordinal值是从 0 开始算起的,所以 Fri 的 ordinal 值为4。
PrettyFormat 格式化输出
默认情况下,输出的 json 只有一行。这个特性可以让输出进行一些格式化操作,什么意思呢,输出会有多行,有缩进,有换行。
String userStr = JSON.toJSONString(user, SerializerFeature.PrettyFormat);
输出:
{
"address":"杭州123号\t\n\r \"京城18号\"",
"age":12,
"defVal":"hello",
"name":"张三",
"sex":"1",
"test":"test",
"week":"Fir"
}
WriteSlashAsSpecial 对 / 进行转义输出
user.setAddress("杭州123号\t\n\r / /\"京城18号\"");
String userStr = JSON.toJSONString(user);
String userStr1 = JSON.toJSONString(user, SerializerFeature.WriteSlashAsSpecial);
输出:
{"address":"杭州123号\t\n\r / /\"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
{"address":"杭州123号\t\n\r \/ \/\"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
默认情况下, / 是原样输出的,加了WriteSlashAsSpecial ,/ 被转义输出为 /
IgnoreNonFieldGetter
忽略类中非 field 字段的 getter 方法。我们看默认情况下,User 类中有一个
getTest()方法,在序列化结果中,出现了一个 test 字段,
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
但是在 User 类中并没有一个 test 属性字段,默认情况下,fastjson 也会把这样的字段序列化出来。加了 IgnoreNonFieldGetter 之后,这样不是类 field 字段对应的getter 方法会被忽略,也就不会序列化出多余的字段了。
String userStr1 = JSON.toJSONString(user, SerializerFeature.IgnoreNonFieldGetter);
输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","week":"Fir"}
test 字段不见了。
WriteDateUseDateFormat,
全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;
JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
user.setBirth(new Date());
String s = JSON.toJSONString(user, SerializerFeature.WriteDateUseDateFormat);
输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"birth":"2019-07-09","defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
birth字段输出为: 2019-07-09。这种方式属于全局修改,所有的日子字段都会转换成相应的格式,如果只想对某次序列化的日期做处理,可以改用
JSON.toJSONStringWithDateFormat(user,"yyyy-MM-dd");
QuoteFieldNames, UseSingleQuotes
QuoteFieldNames特性表示序列化时将 key 用双引号包裹,默认为 true.
输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
UseSingleQuotes 输出key时使用单引号而不是双引号, 默认 false.
代码:
String userStr1 = JSON.toJSONString(user, SerializerFeature.UseSingleQuotes);
输出:
{'address':'杭州123号\t\n\r "京城18号"','age':12,'defVal':'hello','name':'张三','sex':'1','test':'test','week':'Fir'}
key 现在是用单引号包裹的。如果想让 key 既不用双引号括起来,也不用单引号括起来。那么将 QuoteFieldNames 设置为 false。
代码:
int feature = SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.QuoteFieldNames, false);
输出:
{address:"杭州123号\t\n\r \"京城18号\"",age:12,defVal:"hello",name:"张三",sex:"1",test:"test",week:"Fir"}