場景
有時候我們在序列化的時候,做一些脫敏處理历筝,或者做一些類型的轉(zhuǎn)換,比如在java程序中使用的一些特殊的數(shù)據(jù)類型BigDecimal 在傳到前端的時候就在出現(xiàn)解析精度丟失的情況,因為js沒有合適的數(shù)據(jù)類型去接收這個數(shù)據(jù)類目养,所以采取的辦法就是序列化的時候直接把BigDecimal類型轉(zhuǎn)換成String
大概是這樣子
{
"bigDecimal": "0.315675",
"bigDecimal2": 0.316767,
"d": 2222
}
前端在拿到 bigDecimal這個字段直接解析這個字符串顯示到界面,精度就不會丟失财异。
怎么達到這個效果
這里面就需要 實現(xiàn) ValueFilter 這個接口
首先要看 SerializeFilter這個接口是通過編程擴展的方式定制序列化倘零。
fastjson支持6種SerializeFilter,用于不同場景的定制序列化戳寸。
PropertyPreFilter 根據(jù)PropertyName判斷是否序列化
PropertyFilter 根據(jù)PropertyName和PropertyValue來判斷是否序列化
NameFilter 修改Key呈驶,如果需要修改Key,process返回值則可
ValueFilter 修改Value
BeforeFilter 序列化時在最前添加內(nèi)容
AfterFilter 序列化時在最后添加內(nèi)容
我們實現(xiàn)的是 ValueFilter這個
具體看代碼解釋
public class BeanPropertyFilter implements ValueFilter {
private Field field = null;
@Override
public Object process(Object obj, String name, Object value) {
Boolean flag = false;
try {
field = obj.getClass().getDeclaredField(name);
// 獲取注解
flag = field.getAnnotation(FieldToString.class).value().equals("true");
if (flag == true && value != null) {
// 這里 其他類型轉(zhuǎn)換成String類型
value += "";
}
} catch (NoSuchFieldException e) {
return value;
} catch (Exception e) {
return value;
}
return value;
}
}
現(xiàn)在需要在實現(xiàn)一個自定義的注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface FieldToString {
public String value() default "true";
}
注解類就不解釋了
如何使用
class D {
@FieldToString
private BigDecimal bigDecimal;
private BigDecimal bigDecimal2;
private double d;
//此處省略 get set方法
測試下
public static void main(String[] args) {
BeanPropertyFilter beanPropertyFilter=new BeanPropertyFilter();
D d=new D();
d.setBigDecimal(new BigDecimal(0.315675).setScale(6,BigDecimal.ROUND_HALF_UP));
d.setD(2222L);
d.setBigDecimal2(new BigDecimal(0.316767).setScale(6,BigDecimal.ROUND_HALF_UP));
System.out.println(JSON.toJSONString(d,beanPropertyFilter));
}
這是序列化的之后的結果
可以看到在第一個 變量需要里面已經(jīng)轉(zhuǎn)成了String類型,然后其他的變量沒有被轉(zhuǎn)疫鹊,這就達到的預期效果了
{
"bigDecimal": "0.315675",
"bigDecimal2": 0.316767,
"d": 2222
}
效率上怎么樣
在效率上自定義的過濾器中大概測試了一下袖瞻,在循環(huán)十萬次測試,使用自定義序列化和不使用僅僅相差1秒鐘拆吆,完全可以忽略聋迎。