2012-07-03 116 views
21

目前,我正在使用Jackson从我的基于Spring的Web应用程序发出JSON结果。Java到Jackson JSON序列化:Money字段

我遇到的问题是试图让所有的金钱领域输出2位小数。我无法使用setScale(2)解决此问题,因为像25.50这样的数字被截断为25.5等。

有没有其他人处理过这个问题?我正在考虑用定制的Jackson序列化程序制作Money类......你可以为字段变量创建一个自定义的序列化程序吗?您可能可以...但即使如此,我怎么能让我的客户序列化程序将该数字添加为2位小数的数字?

+0

你在存储这些值是什么?一个'BigDecimal'? –

+0

@GregKopff是一个BigDecimal – ControlAltDel

回答

5

我有同样的问题,我把它格式化为JSON作为一个字符串,而不是。可能有点破解,但很容易实现。

private BigDecimal myValue = new BigDecimal("25.50"); 
... 
public String getMyValue() { 
    return myValue.setScale(2, BigDecimal.ROUND_HALF_UP).toString(); 
} 
40

您可以在您的货币字段使用自定义序列化器。这是一个MoneyBean的例子。该字段的数量获得注释@JsonSerialize(使用= ...)

public class MoneyBean { 
    //... 

    @JsonProperty("amountOfMoney") 
    @JsonSerialize(using = MoneySerializer.class) 
    private BigDecimal amount; 

    //getters/setters... 
} 

public class MoneySerializer extends JsonSerializer<BigDecimal> { 
    @Override 
    public void serialize(BigDecimal value, JsonGenerator jgen, SerializerProvider provider) throws IOException, 
      JsonProcessingException { 
     // put your desired money style here 
     jgen.writeString(value.setScale(2, BigDecimal.ROUND_HALF_UP).toString()); 
    } 
} 

就是这样。现在BigDecimal以正确的方式打印出来。我用一个简单的测试用例来表明它:

@Test 
public void jsonSerializationTest() throws Exception { 
    MoneyBean m = new MoneyBean(); 
    m.setAmount(new BigDecimal("20.3")); 

    ObjectMapper mapper = new ObjectMapper(); 
    assertEquals("{\"amountOfMoney\":\"20.30\"}", mapper.writeValueAsString(m)); 
} 
+1

不错的方法,但它将其打印为字符串 - 而不是JSON输出中的数字类型。 – jro

+17

从商业角度来看,这是一种可怕的方法。资金不应该在序列化时四舍五入。如果你想*拖尾*后面的零(不同于盲目设置刻度),那么你必须不使用'ROUND_HALF_UP'。另外,不同的货币期望不同数量的尾随小数。 –

+1

jro,如果在Steve的serialize()中使用writeNumber()而不是writeString(),那么该字段将显示为JSON中的数字。 – caelumvox

16

而不是设置@JsonSerialize每个成员上或吸气剂可以配置使用的是定制串行对于一定类型的模块的:

SimpleModule module = new SimpleModule(); 
module.addSerializer(BigInteger.class, new ToStringSerializer()); 
objectMapper.registerModule(module); 

在上面的例子中,我使用的串序列化器序列化BigIntegers(因为JavaScript无法处理这些数值)。

+1

*我在哪里定义客户序列化程序?这正是我想要做的,但我无法弄清楚代码的放置位置。 – DaveH

+0

只要你喜欢,你只需要实现com.fasterxml.jackson.databind.JsonSerializer – Modi

+0

你能更具体一点吗?我仍然没有把它放在哪里。 – Wouter

4

我是jackson-datatype-money的维护人员之一,因此我肯定有偏见,因此请带着一点盐来回答这个问题。该模块应该涵盖您的需求,并且它相当轻量级(没有额外的运行时依赖)。此外,它在Jackson docs,Spring docs中提到,并且甚至有some discussions已经关于如何将其整合到Jackson的官方生态系统中。

相关问题