使用 GSON 序列化 BigDecimal 值

Serializing BigDecimal value using GSON

这是我的代码:

System.out.println(GSON.toJson(new BigDecimal(10.12)));

输出为:

10.1199999999999992184029906638897955417633056640625

是否可以限制GSON序列化的BigDecimal值的精度?即我的序列化值的预期输出是:

10.11

这不是 GSON 问题。 new BigDecimal() 尝试准确表示 double 并最终占用更多数字。

您可以使用 BigDecimal.valueOf(10.12)new BigDecimal("10.12") 代替 new BigDecimal()

System.out.println(GSON.toJson(BigDecimal.valueOf(10.12)));

与其依赖 BigDecimal 的构造函数,最佳做法是在使用 GSON 序列化之前将其格式化为所需的精度。

BigDecimal提供了一种将其转换为浮点数的方法(floatValue),您可以使用String.format(expr, float)函数将其格式化为您想要的格式。

    BigDecimal value = new BigDecimal(10.12);

    String strValue = String.format("%.2f", value.floatValue());
    System.out.println(GSON.toJson(strValue));

这里的问题不在于 GSON,而是在于您的 BigDecimal 值。

如果您使用 new BigDecimal(double value) 构造函数,您可能会得到不可预知的结果。

如果你看一下 BigDecima(double value) constructor documentation,它清楚地写着:

Notes:

  • The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.

  • The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.

所以这里最好使用BigDecimal String constructor:

new BigDecimal("10.12")