使用Jackson序列化一个Double到2的小数位

mlo*_*o55 32 java jackson

我正在使用Jackson,Spring MVC写出一些简单的对象JSON.其中一个对象具有amount类型的属性Double.(我知道这Double不应该用作金额.但是,这不是我的代码.)

JSON输出中,我想将数量限制为2位小数.目前它显示为:

"amount":459.99999999999994
Run Code Online (Sandbox Code Playgroud)

我已经尝试过使用Spring 3的@NumberFormat注释,但是没有在这方面取得成功.看起来其他人也有问题:在这里将JSON绑定到JavaBean propertiesenter链接描述时,MappingJacksonHttpMessageConverter的ObjectMapper不使用ConversionService.

此外,我尝试使用@JsonSerialize注释,使用自定义序列化程序.
在模型中:

@JsonSerialize(using = CustomDoubleSerializer.class)
public Double getAmount()
Run Code Online (Sandbox Code Playgroud)

和序列化器实现:

public class CustomDoubleSerializer extends JsonSerializer<Double> {
    @Override
    public void serialize(Double value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
        if (null == value) {
            //write the word 'null' if there's no value available
            jgen.writeNull();
        } else {
            final String pattern = ".##";
            //final String pattern = "###,###,##0.00";
            final DecimalFormat myFormatter = new DecimalFormat(pattern);
            final String output = myFormatter.format(value);
            jgen.writeNumber(output);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

CustomDoubleSerializer"出现"工作.但是,任何人都可以建议任何其他更简单(或更标准)的方法.

小智 5

我在我的项目中遇到了类似的情况。我已将格式化代码添加到 POJO 的 setter 方法中。DecimalFormatter、Math 和其他类最终对值进行了四舍五入,但是,我的要求不是对值进行四舍五入,而只是将显示限制为小数点后 2 位。

我重新创建了这个场景。Product 是一个有成员的 POJO Double amount。JavaToJSON 是一个将创建 Product 实例并将其转换为 JSON 的类。setter setAmountinProduct将负责格式化到小数点后两位。

这是完整的代码。

产品.java

package com;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Product {

    private String name;
    private Double amount;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Double getAmount() {
        return amount;
    }
    public void setAmount(Double amount) {
        BigDecimal bd = new BigDecimal(amount).setScale(2, RoundingMode.FLOOR);
        this.amount = bd.doubleValue();
    }

    @Override
    public String toString() {
        return "Product [name=" + name + ", amount=" + amount + "]";
    }
}
Run Code Online (Sandbox Code Playgroud)

JavaToJSON.java

package com;

import java.io.File;
import java.io.IOException;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

public class JavaToJSON {

    public static void main(String[] args){

        ObjectMapper mapper = new ObjectMapper();

        try {
            Product product = new Product();
            product.setName("TestProduct");
            product.setAmount(Double.valueOf("459.99999999999994"));

            // Convert product to JSON and write to file
            mapper.writeValue(new File("d:\\user.json"), product);

            // display to console
            System.out.println(product);

        } catch (JsonGenerationException e) {

            e.printStackTrace();

        } catch (JsonMappingException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }
    }

}
Run Code Online (Sandbox Code Playgroud)

我没有积累足够的积分,所以我无法上传屏幕截图以向您展示输出。

希望这可以帮助。

  • 你不需要截图。如果你想显示结果,只需在开头做几行空格(就像你用代码做的那样) (2认同)

rus*_*tyx 5

我知道Double不应将其用作货币金额。但是,这不是我的代码。

确实,它不应该。BigDecimal是存储货币金额的更好选择,因为它无损 并且可以控制小数位。

因此,对于确实可以控制代码的人,可以这样使用它:

double amount = 111.222;
setAmount(new BigDecimal(amount).setScale(2, BigDecimal.ROUND_HALF_UP));
Run Code Online (Sandbox Code Playgroud)

这将序列化为111.22。无需自定义序列化器。


the*_*eme -4

请注意,459.99999999999994 实际上是 460,预计会以这种方式进行序列化。所以,你的逻辑应该比仅仅删除数字更棘手。我可能会建议这样的事情:

Math.round(value*10)/10.0
Run Code Online (Sandbox Code Playgroud)

您可能想将其放入 setter 中,并摆脱自定义序列化。

  • 像这样更改值仍然会导致序列化时带有重要尾随数字的数字。舍入_严格来说_是一个表示问题。在 Chrome 控制台中尝试此操作,例如 - `(Math.round(Math.PI * 10) / 10.0).toFixed(20)`。输出不是“3.10000000000000000000”而是“3.10000000000000008882”。 (2认同)
  • 两种语言对 IEEE-754 浮点数学的处理是相同的。 (2认同)