public enum SerializerFeature {
/**
* 对键加双引号
*/
QuoteFieldNames,
/**
* 使用单引号代替双引号
*/
UseSingleQuotes,
/**
* 输出空值(null)
*/
WriteMapNullValue,
/**
* 用枚举toString()值输出
*/
WriteEnumUsingToString,
/**
* 用枚举name()输出
*/
WriteEnumUsingName,
/**
* 对日期进行2016-09-23T23:11:56.550这样的格式化
*/
UseISO8601DateFormat,
/**
* @since 1.1
* 如果一个List(实现了List接口)为null 则输出[]
*/
WriteNullListAsEmpty,
/**
* @since 1.1
* 如果一个字符串为null,则输出""
*/
WriteNullStringAsEmpty,
/**
* @since 1.1
* 数字字段输出0 而不是null
*/
WriteNullNumberAsZero,
/**
* @since 1.1
* 如果一个Boolean变量为null,则输出false
*/
WriteNullBooleanAsFalse,
/**
* @since 1.1
* 不输出transient修饰的变量
*/
SkipTransientField,
/**
* @since 1.1
* 对字段进行排序
*/
SortField,
/**
* @since 1.1.1
*/
@Deprecated
WriteTabAsSpecial,
/**
* @since 1.1.2
* 格式化输出
*/
PrettyFormat,
/**
* @since 1.1.2
* 输出类的名字
*/
WriteClassName,
/**
* @since 1.1.6
* 对于值相同的键,不使用引用表达
* 不使用类似于下面的方式来输出:
* {"$ref":"$"} 引用根对象
* {"$ref":"@"} 引用自己
* {"$ref":".."} 引用父对象
* {"$ref":"../.."} 引用父对象的父对象
* {"$ref":"$.members[0].reportTo"} 基于路径的引用
*/
DisableCircularReferenceDetect,
/**
* @since 1.1.9
* 把正斜线/当做特殊字符
*/
WriteSlashAsSpecial,
/**
* @since 1.1.10
* 为了浏览器兼容问题,把中文转换为\u4E2D这样的Unicode码
*/
BrowserCompatible,
/**
* @since 1.1.14
* 使用2016-09-19 16:19:05这样的格式格式化日期
*/
WriteDateUseDateFormat,
/**
* @since 1.1.15
*/
NotWriteRootClassName,
/**
* @since 1.1.19
* 对特殊字符进行转义,例如" 换为\"
*/
DisableCheckSpecialChar,
/**
* @since 1.1.35
* 按["field1",field2,field3,"field4","field5","field6"]
* 这样的格式来输出bean
*/
BeanToArray,
/**
* @since 1.1.37
* 把所有的键都作为String
*/
WriteNonStringKeyAsString,
/**
* @since 1.1.42
* 不输出默认值
*/
NotWriteDefaultValue,
/**
* @since 1.2.6
*/
BrowserSecure,
/**
* @since 1.2.7
* 忽略没有getter的字段
*/
IgnoreNonFieldGetter
;
SerializerFeature(){
mask = (1 << ordinal());
}
private final int mask;
public final int getMask() {
return mask;
}
/**
* 判断features所代表的特性集合中是否包含有feature特性
* 这里巧妙的使用了一个掩码(mask)来计算,mask是通过对1进行移位得到的
* 因为每一个SerializerFeature在枚举中的序数是固定的,所以mask的
* 值就是像下面的二进制形式:
* 00000000000000000000000000000001
* 00000000000000000000000000000010
* 00000000000000000000000000000100
* 00000000000000000000000000001000
* ......
* 10000000000000000000000000000000
* 所以通过&运算很容易就判断出features中有没有feature。例如:
* feature是WriteMapNullValue(0000000000000000000000000000100),
* features是15(0000000000000000000000000001111),很容易知道features
* 中包含有feature。(可通过SerializerFeature数组计算features,下面提供的
* of方法就可以计算features的值(SerializerFeature数组的掩码(mask)))
* @param features
* @param feature
* @return
*/
public static boolean isEnabled(int features, SerializerFeature feature) {
return (features & feature.getMask()) != 0;
}
/**
* 检查features或者fieaturesB是否包含feature
* 和上一个方法一样
* @param features
* @param fieaturesB
* @param feature
* @return
*/
public static boolean isEnabled(int features, int fieaturesB, SerializerFeature feature) {
int mask = feature.getMask();
return (features & mask) != 0 || (fieaturesB & mask) != 0;
}
/**
* 为features增加feature特性,或者剔除feature特性
* 当state为true时为features增加feature特性
* 当state为false时为features剔除feature特性
* @param features
* @param feature
* @param state
* @return
*/
public static int config(int features, SerializerFeature feature, boolean state) {
if (state) {
features |= feature.getMask();
} else {
features &= ~feature.getMask();
}
return features;
}
/**
* 计算SerializerFeature数组的掩码(mask)
* 通过|运算把features中的特性叠加起来
* @param features
* @return
*/
public static int of(SerializerFeature[] features) {
if (features == null) {
return 0;
}
int value = 0;
for (SerializerFeature feature: features) {
value |= feature.getMask();
}
return value;
}
}
SerializerFeature是一个枚举类型,现在包含有17个枚举值。可以通过每一个枚举值来控制在转化为json字符串的行为。比较常用的是:
WriteNullStringAsEmpty 如果一个字符串为null,则输出""
WriteNullNumberAsZero 数字字段输出0 而不是null
DisableCircularReferenceDetect 不使用应用表达
WriteDateUseDateFormat 使用2016-09-19 16:19:05这样的格式格式化日期
SerializerFeature中使用的技巧也是非常值得学习的,例如,在isEnable中巧妙的使用了一个掩码(mask)来计算,mask是通过对1进行移位得到的因为每一个SerializerFeature在枚举中的序数是固定的,所以mask的值就是像下面的二进制形式:
00000000000000000000000000000001
00000000000000000000000000000010
00000000000000000000000000000100
00000000000000000000000000001000
......
10000000000000000000000000000000
所以通过&运算很容易就判断出features中有没有feature。例如:
feature是WriteMapNullValue(0000000000000000000000000000100),
features是15(0000000000000000000000000001111),很容易知道features
中包含有feature。(可通过SerializerFeature数组计算features,下面提供的
of方法就可以计算features的值(SerializerFeature数组的掩码(mask)))
既然提到了of方法就先说of方法。首先SerializerFeature中的枚举值是兼容的而不是相互排斥的,例如,既要如果一个字符串为null,则输出"",又要使用2016-09-19 16:19:05这样的格式格式化日期,那么就WriteNullStringAsEmpty,WriteDateUseDateFormat 这两个枚举值,在fastjson中可以通过SerializerFeature数组来表示。而fastjson中很多时候是通过一个int类型的数字来表示,根据前面提到的很容易想到对WriteNullStringAsEmpty,WriteDateUseDateFormat 的mask做亦或(|)运算,而实际上SerializerFeature的of方法就是这么干的。所以需要isEnable方法来判读一个int类型的值中是不是包含有某一个SerializerFeature。
很自然的我们想到要为一个features增加一个feature或者从features中剔除一个feature,于是config方法来了。先说添加features |= feature.getMask();一句代码就搞定了,如果你把前面isEnable的注释读清楚了这句就很好理解了,先获取到要添加feature的mask,在做一回运算,亦或运算时只要有一个是1就是1,就是如果features对应位上没有1就把它置为1。同理,从features中剔除feature也是一句代码features &= ~feature.getMask();&运算的特点是有一个为0就为0,这里先把要剔除的feature的mask然后取反,就是把该feature对应位上置0,然后利用&运算的特点把features中feature对应位上的值置0。config的代码非常简洁,不得不说fastjson作者的代码功底的确很棒。