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做者的代码功底的确很棒。对象