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字符串的行爲。比較經常使用的是:java
WriteNullStringAsEmpty 若是一個字符串爲null,則輸出""json
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)))code
既然提到了of方法就先說of方法。首先SerializerFeature中的枚舉值是兼容的而不是相互排斥的,例如,既要若是一個字符串爲null,則輸出"",又要使用2016-09-19 16:19:05這樣的格式格式化日期,那麼就WriteNullStringAsEmpty,WriteDateUseDateFormat 這兩個枚舉值,在fastjson中能夠經過SerializerFeature數組來表示。而fastjson中不少時候是經過一個int類型的數字來表示,根據前面提到的很容易想到對WriteNullStringAsEmpty,WriteDateUseDateFormat 的mask作亦或(|)運算,而實際上SerializerFeature的of方法就是這麼幹的。因此須要isEnable方法來判讀一個int類型的值中是否是包含有某一個SerializerFeature。orm
很天然的咱們想到要爲一個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做者的代碼功底的確很棒。對象