记录一次alibaba.fastjson,Double类型被转换为BigDecimal类型解决方法

记录一次alibaba.fastjson,Double类型被转换为BigDecimal类型解决方法

  • 问题描述
    • 查询问题
    • 如何解决

问题描述

在一次开发过程当中遇到的一个关于FastJson的问题,我获取到的数据对象是一种无规则的json字符串,需要转换为JsonObject对象后存入到MongDB里面。但是在数据提交到MongoDB时发现,原本提交的Double类型保存到MongoDB的时候发现这个数据类型变成了String类型。因为在mongo中使用了2dsphere,也出现了Can’t extract geo keys错误信息。

查询问题

测试代码

class TestEntity {
    private Double doubleVal;
    private Float floatVal;
    private String name;

    public Double getDoubleVal() {
        return doubleVal;
    }

    public void setDoubleVal(Double doubleVal) {
        this.doubleVal = doubleVal;
    }

    public Float getFloatVal() {
        return floatVal;
    }

    public void setFloatVal(Float floatVal) {
        this.floatVal = floatVal;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class JSONTest {
    public static void main(String[] args) {
        TestEntity testEntity = new TestEntity();
        testEntity.setDoubleVal(123.456001);
        testEntity.setFloatVal(123.45512F);
        testEntity.setName("测试FastJSON");
        String str = JSON.toJSON(testEntity).toString();
        JSONObject JB = JSON.parseObject(str);
        System.out.println("***** Test Start ******");
        System.out.println("doubleVal = " + JB.get("doubleVal"));
        System.out.println("floatVal = " + JB.get("floatVal"));
        System.out.println("name = " + JB.get("name"));
    }
}

开始debug代码查找具体的问题出现在哪里。经过的debug发现在使用alibaba的fastJson转换的时候原数据里面的Double类型被转换成了BigDecimal。如下图所示
记录一次alibaba.fastjson,Double类型被转换为BigDecimal类型解决方法_第1张图片
然后开始查看所调用的API文档,最终定位到问题所在
在JSON类里面的静态代码块

static {
        int features = 0;
        int features = features | Feature.AutoCloseSource.getMask();
        features |= Feature.InternFieldNames.getMask();
        features |= Feature.UseBigDecimal.getMask();
        features |= Feature.AllowUnQuotedFieldNames.getMask();
        features |= Feature.AllowSingleQuotes.getMask();
        features |= Feature.AllowArbitraryCommas.getMask();
        features |= Feature.SortFeidFastMatch.getMask();
        features |= Feature.IgnoreNotMatch.getMask();
        DEFAULT_PARSER_FEATURE = features;
        features = 0;
        features = features | SerializerFeature.QuoteFieldNames.getMask();
        features |= SerializerFeature.SkipTransientField.getMask();
        features |= SerializerFeature.WriteEnumUsingName.getMask();
        features |= SerializerFeature.SortField.getMask();
        String featuresProperty = IOUtils.getStringProperty("fastjson.serializerFeatures.MapSortField");
        int mask = SerializerFeature.MapSortField.getMask();
        if("true".equals(featuresProperty)) {
            features |= mask;
        } else if("false".equals(featuresProperty)) {
            features &= ~mask;
        }

        DEFAULT_GENERATE_FEATURE = features;
        bytesLocal = new ThreadLocal();
        charsLocal = new ThreadLocal();
    }

在JSON类里面的静态代码块的第五行发现了 features |= Feature.UseBigDecimal.getMask();
通过对Feature类的查询发现UseBigDecimal这个设置是用来使用BigDecimal来装载数字的,否则使用Double。但是在JSON类中的静态代码块中默认设置为了True。

如何解决

出现问题就开始各种BD、Google问题。最终在全球最大的男性交流平台的官方仓库的Wiki中找到了答案
链接: github deserialize_disable_bigdecimal_cn.
按照Wiki的方法进行了下修改,解决了问题。

		TestEntity testEntity = new TestEntity();
        testEntity.setDoubleVal(123.456001);
        testEntity.setFloatVal(123.45512F);
        testEntity.setName("测试FastJSON");
        int disableDecimalFeature = JSON.DEFAULT_PARSER_FEATURE & ~Feature.UseBigDecimal.getMask();
        String str = JSON.toJSON(testEntity).toString();
        //JSONObject JB = JSON.parseObject(str);
        JSONObject JB = JSON.parseObject(str,JSONObject.class,disableDecimalFeature);
        System.out.println("***** Test Start ******");
        System.out.println("doubleVal = " + JB.get("doubleVal"));
        System.out.println("floatVal = " + JB.get("floatVal"));
        System.out.println("name = " + JB.get("name"));

记录一次alibaba.fastjson,Double类型被转换为BigDecimal类型解决方法_第2张图片
不过Float类型还是变成了Double类型,这个问题还没有解决掉。

说实话还有一个坑就是在使用FastJson的时候有时候序列化以后变成无序的状态,这个时候就要使用 Feature.OrderedField 这个特性,因为默认是未开启的

JSONObject JB = JSON.parseObject(str,JSONObject.class,disableDecimalFeature,Feature.OrderedField);

以上解决掉了所有问题了,感谢提供帮助的群里的小伙伴。

你可能感兴趣的:(踩过的坑)