web-dev-qa-db-ja.com

Java to Jackson JSON serialization:Money fields

現在、Jacksonを使用して、SpringベースのWebアプリケーションからJSON結果を送信しています。

私が抱えている問題は、すべての金額フィールドを小数点以下2桁で出力しようとしています。 setScale(2)を使用してこの問題を解決することはできませんでした。25.50のような数値は25.5などに切り捨てられるためです。

他の誰かがこの問題に対処しましたか?カスタムジャクソンシリアライザーでMoneyクラスを作成することを考えていました...フィールド変数のカスタムシリアライザーを作成できますか?おそらく...しかし、それでも、顧客のシリアライザーに、小数点以下2桁の数値として数値を追加するにはどうすればよいでしょうか。

40
ControlAltDel

マネーフィールドでカスタムシリアライザーを使用できます。 MoneyBeanの例を次に示します。フィールドamountには@ 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));
}
63
Steve

各メンバーまたはゲッターで@JsonSerializeを設定する代わりに、特定のタイプのカスタムシリアライザーを使用するモジュールを構成できます。

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

上記の例では、to string serializerを使用してBigIntegerをシリアル化しました(javascriptはそのような数値を処理できないため)。

24
Modi

shape変数でSTRINGとしてBigDecimalとして@JsonFormatアノテーションを使用できます。以下を参照してください:

 import com.fasterxml.jackson.annotation.JsonFormat;

  class YourObjectClass {

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

 }
23
Sahil Chhabra

私は jackson-datatype-money のメンテナーの1人です。したがって、私は確かに偏っているので、この答えを一粒の塩で取ります。モジュールはあなたのニーズをカバーするはずで、かなり軽量です(追加のランタイム依存関係はありません)。さらに、それは Jackson docsSpring docs で言及されており、ジャクソンの公式のエコシステムにそれを統合する方法についてはすでに 一部の議論 がありました。

13
whiskeysierra

私は同じ問題を抱えており、代わりに文字列としてJSONにフォーマットしました。ちょっとしたハックかもしれませんが、実装は簡単です。

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