fastjson SerializerFeature


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

转载于:https://my.oschina.net/u/2474629/blog/748752

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值