fastjson配置SerializerFeature.WriteBigDecimalAsPlain无效

java | 2019-09-23 13:57:42

配置SerializerFeature.WriteBigDecimalAsPlain无效现象:

@Getter
@Setter
public static class TradeAccount{
    private BigDecimal amount;
}
 
@Test
public void testLog(){
    BigDecimal bigDecimal = new BigDecimal("0.00000005");
    HashMap map = new HashMap<>();
    map.put("amount", bigDecimal);
    System.out.println(JSON.toJSONString(map, SerializerFeature.WriteBigDecimalAsPlain));
    
    TradeAccount tradeAccount = new TradeAccount();
    tradeAccount.setAmount(bigDecimal);
    System.out.println(JSON.toJSONString(tradeAccount, SerializerFeature.WriteBigDecimalAsPlain));
}

结果:

{"amount":0.00000005}
{"amount":5E-8}

说明SerializerFeature.WriteBigDecimalAsPlain配置没有效果 查看源码:

public void writeFieldValue(char seperator, String name, BigDecimal value) {
    write(seperator);
    writeFieldName(name);
    if (value == null) {
        writeNull();
    } else {
        write(value.toString());//value.toString()导致
    }

这个可能是fastjson的一个bug.

解决方法有三种

方法一.添加一个SerializeFilter

@Test
    public void testLog(){
        TradeAccount tradeAccount = new TradeAccount();
        tradeAccount.setAmount(new BigDecimal("0.00000005"));
        System.out.println(JSON.toJSONString(tradeAccount, new ValueFilter() {
            @Override
            public Object process(Object object, String name, Object value) {
                if(value instanceof BigDecimal) {
                    return((BigDecimal)value).toPlainString();
                }
                return value;
            }
        }));
    }

 

结果:

{"amount":"0.00000005"}

这种方法比较简单 但有一个缺点 结果变为字符串.方法二可以解决这个问题

 

方法二:添加两个SerializeFilter

 


    @Test
    public void testLog(){
        TradeAccount tradeAccount = new TradeAccount();
        tradeAccount.setAmount(new BigDecimal("0.00000005"));
        AfterFilter afterFilter = new AfterFilter() {
            @Override
            public void writeAfter(Object object) {
                Field[] fields = object.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.getType() == BigDecimal.class) {
                        field.setAccessible(true);
                        Object value= null;
                        try {
                            value = field.get(object);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        writeKeyValue(field.getName(), value );
                    }
                }
            }
        };
        PropertyFilter filter = new PropertyFilter() {
            @Override
            public boolean apply(Object source, String name, Object value) {
                if (value instanceof BigDecimal) {
                    return false;
                }
                return true;
            }
        };
        System.out.println(JSON.toJSONString(tradeAccount, new SerializeFilter[]{afterFilter, filter},
            SerializerFeature.WriteBigDecimalAsPlain));
    }

结果:

{"amount":0.00000005}

方法二原理就是不使用fastjson 默认序列化BigDecimal类型的字段的方法,而自己调用

com.alibaba.fastjson.serializer.BigDecimalCodec(SerializerFeature.WriteBigDecimalAsPlain配置对此方法有效)

 

方法三:自定义序列化方法

public static  class BigDecimalSerializer implements ObjectSerializer {
        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features){
            SerializeWriter out = serializer.out;
            BigDecimal value = (BigDecimal)object;
            out.writeString(value.toPlainString());
        }
    }
 
    @Getter
    @Setter
    public static class TradeAccount{
        @JSONField(serializeUsing = BigDecimalSerializer.class)
        private BigDecimal amount;
    }
 
    @Test
    public void testLog(){
        TradeAccount tradeAccount = new TradeAccount();
        tradeAccount.setAmount(new BigDecimal("0.00000005"));
        System.out.println(JSON.toJSONString(tradeAccount));
    }

 

此方法类似方法一 但是需要添加注解 所以不能作为序列化的默认方法 如spring boot 将fastjson作为序列化工具类:

@Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        FastJsonHttpMessageConverter4 fastConverter=new FastJsonHttpMessageConverter4();
        FastJsonConfig fastJsonConfig=new FastJsonConfig();
        fastJsonConfig.setSerializeFilters(new ValueFilter() {
            @Override
            public Object process(Object object, String name, Object value) {
                if(value instanceof BigDecimal) {
                    return ((BigDecimal)value).toPlainString();
                }
                return value;
            }
        });
        fastConverter.setFastJsonConfig(fastJsonConfig);
 
        fastConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
        converters.add(fastConverter);
    }

 

 

登录后即可回复 登录 | 注册
    
关注编程学问公众号