簡體   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