繁体   English   中英

Java 到 Jackson JSON 序列化:货币字段

[英]Java to Jackson JSON serialization: Money fields

目前,我正在使用 Jackson 从基于 Spring 的 Web 应用程序发送 JSON 结果。

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

还有其他人处理过这个问题吗? 我正在考虑使用自定义 Jackson 序列化程序制作 Money 类......你可以为字段变量制作自定义序列化程序吗? 你可能可以......但即便如此,我如何让我的客户序列化程序将数字添加为小数点后两位的数字?

您可以在 money 字段中使用自定义序列化程序。 下面是 MoneyBean 的示例。 字段数量@JsonSerialize(using=...)注释。

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));
}

您可以在BigDecimal变量上使用带有shape@JsonFormat注释作为STRING 参考以下:

 import com.fasterxml.jackson.annotation.JsonFormat;

  class YourObjectClass {

      @JsonFormat(shape=JsonFormat.Shape.STRING)
      private BigDecimal yourVariable;

 }

无需在每个成员或 getter 上设置 @JsonSerialize,您可以配置一个模块,该模块使用特定类型的自定义序列化程序:

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

在上面的例子中,我使用了 to string serializer 来序列化 BigIntegers(因为 javascript 不能处理这样的数值)。

我是jackson-datatype-money的维护者之一,所以对这个答案持保留态度,因为我肯定有偏见。 该模块应该满足您的需求,而且它非常轻巧(没有额外的运行时依赖项)。 此外, Jackson 文档Spring 文档中也提到了它,甚至已经有一些关于如何将其集成到 Jackson 官方生态系统中的讨论。

我有同样的问题,我将它格式化为 JSON 作为字符串。 可能有点 hack,但很容易实现。

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

正如Sahil Chhabra建议的那样,您可以在变量上使用具有适当shape@JsonFormat 如果您想将它应用于Dto's每个BigDecimal字段,您可以覆盖给定类的默认格式。

@Configuration
public class JacksonObjectMapperConfiguration {

    @Autowired
    public void customize(ObjectMapper objectMapper) {
         objectMapper
            .configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
    }
}

Steve的启发,作为 Java 11 的更新。以下是我们如何进行 BigDecimal 重新格式化以避免科学记数法。

public class PriceSerializer extends JsonSerializer<BigDecimal> {
    @Override
    public void serialize(BigDecimal value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        // Using writNumber and removing toString make sure the output is number but not String.
        jgen.writeNumber(value.setScale(2, RoundingMode.HALF_UP));
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM