zoukankan      html  css  js  c++  java
  • fastjson 处理 double 的精度问题

    项目中使用 fastjson 来处理 json 格式,当前使用的版本为1.1.37。在和其它系统交互时,将一个json串传给了对方,原值为5.0,json 处理后格式为:{"dou", 5}; 结果对方处理该串报错了, 原因是他将串整理转成 Map ,在取值时强制转为了 Double ,因为拿到的值转化是 Integer 类型,强转肯定异常了。 简单的做法应该通过 Double.valueOf(value)  进行处理。但无奈合作方不愿意处理。 于是测试了下fastjson处理这个串时,通过以下做处理, 输出的结果为 {"dou", 5}。

    JSONObject jsonObject = new JSONObject();
    Double dou = new Double(5.0);
    jsonObject.put("dou", dou);
    System.out.println(JSON.toJSONString(jsonObject));

    想要输出{"dou",5.0} 怎么办, 跟踪了下源码,发现在 DoubleSerializer 的 write 方法中,判断了结尾如果是.0 就截掉了。

    doubleText = Double.toString(doubleValue);
    if(doubleText.endsWith(".0")) {
        doubleText = doubleText.substring(0, doubleText.length() - 2);
    }

    那想要的格式怎么办,可以通过自定义 filter 方式实现,:

     ValueFilter filter = new ValueFilter() {
                @Override
                public Object process(Object object, String name, Object value) {
                    if(value instanceof BigDecimal || value instanceof Double || value instanceof Float){
                        return new BigDecimal(value.toString());
                    }
                    return value;
                }
            };
    
    String s  = JSON.toJSONString(jsonObject, filter, new SerializerFeature[0]);

    以上可以完美解决。后来想有没有跟好的方法呢。 于是网上搜索了一下,大多数都是这种做法,并且有人认为这是一个bug,于是突然想有没有可能 wenshao 会处理一下,于是在 github 找到 fastjson 的最新版本 1.2.23。 先修改 pom 文件,然后运行。发现即使不处理也能输出了 {"dou",5.0} 。 于是 debug 进去原来对 DoubleSerializer 进行了重写,并在 write 方法中原来处理格式的地方修改为如下:

    if (decimalFormat == null) {
        out.writeDouble(doubleValue, true);
    } else {
        String doubleText = decimalFormat.format(doubleValue);
        out.write(doubleText);
    }
    
    //out SerializeWriter
    String doubleText = Double.toString(doubleValue);
    if (isEnabled(SerializerFeature.WriteNullNumberAsZero) && doubleText.endsWith(".0")) {
        doubleText = doubleText.substring(0, doubleText.length() - 2);
    }

    即,以上粉色代码调用 SerializeWriter 的writeDouble 方法, 看绿色部分。 同时判断了 SerializerFeature.WriteNullNumberAsZero 和 结尾是否为 .0

    就是通过这个解决了 double 精度的正常输出。  在使用 1.2.23时如果想输出{"dou", 5}, 可以通过设置 SerializerFeature.WriteNullNumberAsZero 实现。

    System.out.println(JSON.toJSONString(jsonObject, SerializerFeature.WriteNullNumberAsZero));

    啰嗦了这么,希望通过升级版本解决同样遇到这样问题的小伙伴。

  • 相关阅读:
    shell习题第12题:批量创建用户
    shell习题第11题:输入数字执行命令
    二、python数据类型、字符编码、文件处理
    C语言之控制语言:分支和跳转
    c语言之控制语句:循环
    C语言之运算符、表达式和语句
    Python集合及其运算
    Python文本处理
    Python迭代器与格式化
    Python装饰器
  • 原文地址:https://www.cnblogs.com/blacksonny/p/6275299.html
Copyright © 2011-2022 走看看